Skip to content

Commit

Permalink
ZOOKEEPER-4880: Generate comments from zookeeper.jute into code.
Browse files Browse the repository at this point in the history
  • Loading branch information
luozongle01 committed Oct 29, 2024
1 parent 837f86c commit 52d4194
Show file tree
Hide file tree
Showing 8 changed files with 857 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.jute.compiler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.jute.compiler.generated.Token;

public class JCommentGenerator {

/**
* {fieldCommentsBeginLineNumber : {fieldCommentsBeginColumn : fieldCommentsToken}}.
*/
private final TreeMap<Integer, TreeMap<Integer, Token>> fieldCommentsTokenMap = new TreeMap<>();

/**
* {recordCommentsBeginLineNumber : {recordCommentsBeginColumn : recordCommentsToken}}.
*/
private final TreeMap<Integer, TreeMap<Integer, Token>> recordCommentsTokenMap = new TreeMap<>();

private final TreeSet<RangeInfo> jFieldTreeSet = new TreeSet<>();

private final TreeSet<RangeInfo> jRecordTreeSet = new TreeSet<>();

public void addJRecord(JRecord jRecord) {
jRecordTreeSet.add(jRecord);
}

public void addJField(JField jField) {
jFieldTreeSet.add(jField);
}

public void putFieldSpecialToken(Token fieldToken) {
putSpecialToken(fieldToken, fieldCommentsTokenMap);
}

public void putRecordSpecialToken(Token recordToken) {
putSpecialToken(recordToken, recordCommentsTokenMap);
}

private static void putSpecialToken(Token classToken, TreeMap<Integer, TreeMap<Integer, Token>> commentsTokenMap) {
if (classToken == null || classToken.specialToken == null || commentsTokenMap == null) {
return;
}

Token tmp = classToken;
while ((tmp = tmp.specialToken) != null && tmp.image != null) {
Token finalTmp = tmp;
commentsTokenMap.compute(tmp.beginLine, (key, value) -> {
if (value == null) {
value = new TreeMap<>();
}
value.putIfAbsent(finalTmp.beginColumn, finalTmp);
return value;
});
}
}

public List<String> getRecordCommentsList(JRecord jRecord) {
return getCommentsList(jRecord, jRecordTreeSet, recordCommentsTokenMap);
}

public List<String> getFieldCommentsList(JField jField) {
return getCommentsList(jField, jFieldTreeSet, fieldCommentsTokenMap);
}

private static List<String> getCommentsList(RangeInfo rangeInfo,
TreeSet<RangeInfo> rangeInfoSet,
NavigableMap<Integer, TreeMap<Integer, Token>> commentsTokenMap) {
if (rangeInfo == null || rangeInfoSet == null || commentsTokenMap == null || commentsTokenMap.isEmpty()) {
return Collections.emptyList();
}

RangeInfo prevRangeInfo = rangeInfoSet.lower(rangeInfo);
RangeInfo nextRangeInfo = rangeInfoSet.higher(rangeInfo);

int beginLine = getBeginLine(rangeInfo, prevRangeInfo);
int beginColumn = getBeginColumn(rangeInfo, nextRangeInfo);
int endLine = rangeInfo.getEndLine();
int endColumn = getEndColumn(rangeInfo, nextRangeInfo);

NavigableMap<Integer, TreeMap<Integer, Token>> lineRangeMap = commentsTokenMap.subMap(beginLine, true, endLine, true);
if (lineRangeMap == null || lineRangeMap.isEmpty()) {
return Collections.emptyList();
}

ArrayList<String> commentList = new ArrayList<>();
Iterator<Map.Entry<Integer, TreeMap<Integer, Token>>> lineIterator = lineRangeMap.entrySet().iterator();
while (lineIterator.hasNext()) {
Map.Entry<Integer, TreeMap<Integer, Token>> lineEntry = lineIterator.next();
if (lineEntry.getValue() == null || lineEntry.getValue().isEmpty()) {
lineIterator.remove();
continue;
}

NavigableMap<Integer, Token> columnMap;
if (lineEntry.getKey() == beginLine) {
columnMap = lineEntry.getValue()
.subMap(beginColumn, true, beginLine == endLine ? endColumn : Integer.MAX_VALUE, true);
} else if (lineEntry.getKey() == endLine) {
columnMap = lineEntry.getValue().subMap(0, true, endColumn, true);
} else {
columnMap = lineEntry.getValue();
}

if (columnMap == null || columnMap.isEmpty()) {
continue;
}

Iterator<Map.Entry<Integer, Token>> columnIterator = columnMap.entrySet().iterator();
while (columnIterator.hasNext()) {
Map.Entry<Integer, Token> entry = columnIterator.next();
columnIterator.remove();

Optional.of(entry)
.map(Map.Entry::getValue)
.map(token -> token.image)
.filter(image -> !image.isEmpty())
.ifPresent(commentList::add);
}

if (lineEntry.getValue().isEmpty()) {
lineIterator.remove();
}
}

return commentList;
}

private static int getBeginLine(RangeInfo thisRangeInfo, RangeInfo prevRangeInfo) {
if (thisRangeInfo == null || prevRangeInfo == null) {
return 0;
}

if (prevRangeInfo.getEndLine() == thisRangeInfo.getBeginLine()) {
return prevRangeInfo.getEndLine();
}

return prevRangeInfo.getEndLine() + 1;
}

private static int getBeginColumn(RangeInfo thisRangeInfo, RangeInfo prevRangeInfo) {
if (thisRangeInfo == null || prevRangeInfo == null) {
return 0;
}

if (prevRangeInfo.getEndLine() == thisRangeInfo.getBeginLine()) {
return thisRangeInfo.getBeginColumn();
}

return 0;
}

private static int getEndColumn(RangeInfo thisRangeInfo, RangeInfo nextRangeInfo) {
if (thisRangeInfo == null || nextRangeInfo == null) {
return Integer.MAX_VALUE;
}

if (thisRangeInfo.getEndLine() == nextRangeInfo.getBeginLine()) {
return nextRangeInfo.getBeginColumn() - 1;
}

return Integer.MAX_VALUE;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
/**
*
*/
public class JField {
public class JField extends RangeInfo {
private JType mType;
private String mName;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;

/**
*
Expand All @@ -37,17 +38,20 @@ public class JRecord extends JCompType {
private String mModule;
private List<JField> mFields;

private JCommentGenerator jCommentGenerator;

/**
* Creates a new instance of JRecord.
*/
public JRecord(String name, ArrayList<JField> flist) {
public JRecord(String name, ArrayList<JField> flist, JCommentGenerator commentGenerator) {
super("struct " + name.substring(name.lastIndexOf('.') + 1),
name.replaceAll("\\.", "::"), getCsharpFQName(name), name, "Record", name, getCsharpFQName("IRecord"));
mFQName = name;
int idx = name.lastIndexOf('.');
mName = name.substring(idx + 1);
mModule = name.substring(0, idx);
mFields = flist;
jCommentGenerator = commentGenerator;
}

public String getName() {
Expand Down Expand Up @@ -208,8 +212,18 @@ public void genCCode(FileWriter h, FileWriter c) throws IOException {
}
}
String recName = getName();

String recordComments = getRecordComments();
if (recordComments != null && !recordComments.isEmpty()) {
h.write(recordComments);
}
h.write("struct " + recName + " {\n");
for (JField f : mFields) {

String fieldComments = getCFieldComments(f);
if (fieldComments != null && !fieldComments.isEmpty()) {
h.write(fieldComments);
}
h.write(f.genCDecl());
}
h.write("};\n");
Expand Down Expand Up @@ -436,10 +450,19 @@ public void genJavaCode(File outputDirectory) throws IOException {
jj.write("import org.apache.jute.*;\n");
jj.write("import org.apache.jute.Record; // JDK14 needs explicit import due to clash with java.lang.Record\n");
jj.write("import org.apache.yetus.audience.InterfaceAudience;\n");
String recordComments = getRecordComments();
if (recordComments != null && !recordComments.isEmpty()) {
jj.write(recordComments);
}
jj.write("@InterfaceAudience.Public\n");
jj.write("public class " + getName() + " implements Record {\n");
for (Iterator<JField> i = mFields.iterator(); i.hasNext(); ) {
JField jf = i.next();

String fieldComments = getJavaFieldComments(jf);
if (fieldComments != null && !fieldComments.isEmpty()) {
jj.write(fieldComments);
}
jj.write(jf.genJavaDecl());
}
jj.write(" public " + getName() + "() {\n");
Expand Down Expand Up @@ -767,4 +790,53 @@ public static String getCsharpFQName(String name) {
}
return fQName.toString();
}

private String getJavaFieldComments(JField jField) {
StringJoiner javaFieldCommentsJoiner =
new StringJoiner("\n * ", " /**\n * ", "\n */\n").setEmptyValue("");
return getFieldComments(jField, javaFieldCommentsJoiner);
}

private String getCFieldComments(JField jField) {
StringJoiner cFieldCommentsJoiner =
new StringJoiner("\n * ", " /**\n * ", "\n */\n").setEmptyValue("");
return getFieldComments(jField, cFieldCommentsJoiner);
}

private String getFieldComments(JField jField, StringJoiner fieldCommentsJoiner) {
List<String> fieldSpecialToken = jCommentGenerator.getFieldCommentsList(jField);
return getComments(fieldCommentsJoiner, fieldSpecialToken);
}

private String getRecordComments() {
List<String> classSpecialToken = jCommentGenerator.getRecordCommentsList(this);

StringJoiner recordCommentsJoiner =
new StringJoiner("\n * ", "/**\n * ", "\n */\n").setEmptyValue("");
return getComments(recordCommentsJoiner, classSpecialToken);
}

private static String getComments(StringJoiner commentsJoiner, List<String> commentList) {
if (commentList == null || commentList.isEmpty()) {
return commentsJoiner.toString();
}

for (String commentMulti : commentList) {
if (commentMulti == null || commentMulti.isEmpty()) {
continue;
}

String[] commentArray = commentMulti.split("\n");
for (String comment : commentArray) {

comment = comment.replaceAll("//|/\\*\\*|/\\*|\\*\\*/|\\*/", "")
.replaceAll("^[* ]+", "").trim();

if (!comment.isEmpty()) {
commentsJoiner.add(comment);
}
}
}
return commentsJoiner.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
/**
* Abstract Base class for all types supported by Hadoop Record I/O.
*/
public abstract class JType {
public abstract class JType extends RangeInfo {

private String mCName;
private String mCppName;
Expand Down
Loading

0 comments on commit 52d4194

Please sign in to comment.