package bluej.stride.framedjava.convert;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Stack;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import bluej.parser.JavaParser;
import bluej.parser.ParseFailure;
import bluej.parser.lexer.JavaTokenTypes;
import bluej.parser.lexer.LocatableToken;
import bluej.stride.framedjava.ast.AccessPermission;
import bluej.stride.framedjava.ast.AccessPermissionFragment;
import bluej.stride.framedjava.ast.FilledExpressionSlotFragment;
import bluej.stride.framedjava.ast.JavadocUnit;
import bluej.stride.framedjava.ast.NameDefSlotFragment;
import bluej.stride.framedjava.ast.ParamFragment;
import bluej.stride.framedjava.ast.SuperThis;
import bluej.stride.framedjava.ast.SuperThisFragment;
import bluej.stride.framedjava.ast.ThrowsTypeFragment;
import bluej.stride.framedjava.ast.TypeSlotFragment;
import bluej.stride.framedjava.convert.ConversionWarning.UnsupportedFeature;
import bluej.stride.framedjava.elements.BreakElement;
import bluej.stride.framedjava.elements.CaseElement;
import bluej.stride.framedjava.elements.ClassElement;
import bluej.stride.framedjava.elements.CodeElement;
import bluej.stride.framedjava.elements.CommentElement;
import bluej.stride.framedjava.elements.ConstructorElement;
import bluej.stride.framedjava.elements.ForeachElement;
import bluej.stride.framedjava.elements.IfElement;
import bluej.stride.framedjava.elements.ImportElement;
import bluej.stride.framedjava.elements.InterfaceElement;
import bluej.stride.framedjava.elements.MethodProtoElement;
import bluej.stride.framedjava.elements.NormalMethodElement;
import bluej.stride.framedjava.elements.ReturnElement;
import bluej.stride.framedjava.elements.SwitchElement;
import bluej.stride.framedjava.elements.ThrowElement;
import bluej.stride.framedjava.elements.TryElement;
import bluej.stride.framedjava.elements.VarElement;
import bluej.stride.framedjava.elements.WhileElement;
import bluej.utility.JavaUtils;
import bluej.utility.Utility;
import threadchecker.OnThread;
import threadchecker.Tag;

import static bluej.parser.lexer.JavaTokenTypes.SL_COMMENT;


| A parser for parsing Java with the purpose of converting it to Stride. | | The JavaParser class does not build an AST, but rather makes callbacks | as it parses. Thus it is up to us to keep track of state and build | a Stride AST. We keep track of state in two ways: | | - We have handlers for expressions, statements, etc, rather than a state | machine with say integer states. If we parse a block, we install a | statement handler to accept statements and join them into a list. | Handlers work well where we know in advance that we expect a particular | item. We always use stacks of handlers, because the constructs | can usually nest, so outer handlers are often there waiting for some | inner item to finish and be dealt with. | | - In some other cases, e.g. modifiers, rather than having upfront handlers, | we just build a stack of things we've seen, to be dealt with once | we know what it is later on. | public class JavaStrideParser extends JavaParser{
| The original source code being transformed | private final String source;
| The stack of expression handlers. | The top item, if any, gets passed expression begin/end events. | If the stack is empty, the expression is ignored. | private final Stack<ExpressionBuilder> expressionHandlers = new Stack<>();
| The stack of statement/defintion handlers. | The top item, if any, gets passed completed statements/definitions. | Should never be empty | private final Stack<StatementHandler> statementHandlers = new Stack<>();
| The stack of actual-argument handlers. | The top item, if any, gets passed argument list begin/another/end events. | If the stack is empty, the arguments are ignored. | private final Stack<ArgumentListHandler> argumentHandlers = new Stack<>();
| The stack of types currently being defined. | private final Stack<TypeDefHandler> typeDefHandlers = new Stack<>();
| The stack of methods currently being defined. | private final Stack<MethodBuilder> methods = new Stack<>();
| Types are an awkward case. Sometimes you know in advance that you | expect a type (e.g. after "throws" or "extends"). Other times, you |* only know what a type is for once you've seen later tokens * (e.g. if you see a type in a method, it could be beginning a field * or a method). So we need both handlers for types we expect, | and a list/stack of types we have seen but will handle later. | The rule is simple: if typeHandlers is not empty, that receives | the type. Otherwise, the type gets put on the top of the prevTypes stack. | | Note that types don't nest (unlike, say, expressions), so we don't | have to worry about keeping track of the outermost. | | Also note that typeHandlers are not popped by default; you must | do the popping. | private final Stack<String> prevTypes = new Stack<>(); private final Stack<Consumer<String>> typeHandlers = new Stack<>();
| The stack of if-statements currently being defined. | private final Stack<IfBuilder> ifHandlers = new Stack<>();
| The stack of switch-statements currently being defined. | private final Stack<SwitchHandler> switchHandlers = new Stack<>();
| The stack of for/foreach-statements currently being defined. | private final Stack<ForHandler> forHandlers = new Stack<>();
| The stack of field/variable declarations currently being defined. | private final Stack<FieldOrVarBuilder> curField = new Stack<>();
| Modifiers seen. Each time we start seeing modifiers, we push a new list | on to the stack, then add them to the list at the top of the stack. | When modifiersConsumed is called, we pop the stack. If you want to use | the modifiers, you must peek (NOT pop!) before modifiersConsumed is called. | | I'm fairly confident that modifier lists can't nest, which would mean this | stack is only ever 0 or 1 items high, but it doesn't harm to have a stack | and it fits with the design of everything else. | private final Stack<List<Modifier>> modifiers = new Stack<>();
| Whether we are testing. If so, we use a special string for all warning comments | private final boolean testing;
| A small class to handle the list of warnings | private class WarningManager {
| Any warnings encountered in the conversion process. | private final List<ConversionWarning> warnings = new ArrayList<>();
| Adds a warning, and calls gotComment to add a comment | public void add(ConversionWarning warning) { add(warning, JavaStrideParser.this::gotComment); }
| Adds a warning, and calls the given callback to add a warning comment | public void add(ConversionWarning warning, Consumer<LocatableToken> commentAdd) { warnings.add(warning); LocatableToken dummyToken = new LocatableToken(SL_COMMENT, "// " + (testing ? ("WARNING:" + warning.getClass().getName()) : warning.getMessage())); dummyToken.setPosition(-1, -1, -1, -1, -1, dummyToken.getText().length()); commentAdd.accept(dummyToken); } } private final WarningManager warnings = new WarningManager();
| The top-most StatementHandler, which collects the result of the parse. | private final StatementHandler result = new StatementHandler(false) { public void endBlock() { } };
| The stack of try/catch/finally currently being defined | private Stack<TryBuilder> tries = new Stack<>();
| The name of the package declaration seen in the file (null if none) | private String pkg;
| The list of imports seen in the file. | private final List<String> imports = new ArrayList<>();
| Constructors a parser for the given Java source code. | @param java The source code to parse. | @param testing True if we are testing (alters the unsupported warning comment format) | public JavaStrideParser(String java, boolean testing) { super(new StringReader(java), true); this.source = java; this.testing = testing; statementHandlers.push(result); }
| Gets the list of conversion warnings seen (call after parsing) | public List getWarnings() { return warnings.warnings; } private class SwitchHandler { private Expression expression; private final List<Expression> cases = new ArrayList<>(); private final List<List<CodeElement>> caseContents = new ArrayList<>(); private List<CodeElement> defaultContents; private boolean inDefault; public void gotSwitchExpression(Expression e) { this.expression = e; } public SwitchElement end() { List<CodeElement> caseFrames = new ArrayList<>(); for (int i = 0; i < cases.size(); i++) { caseFrames.add(new CaseElement(null, cases.get(i).toFilled(), caseContents.get(i), true)); } return new SwitchElement(null, expression.toFilled(), caseFrames, defaultContents, true); } public void beginBlock() { withStatement(newHandler()); } private StatementHandler newHandler() { return new StatementHandler(false) { @Override public void endBlock() { storePrevCode(this); JavaStrideParser.this.foundStatement(switchHandlers.pop().end()); } }; } public void gotCase(Expression e) { storePrevCode(null); cases.add(e); withStatement(newHandler()); } private void storePrevCode(StatementHandler handler) { List<CodeElement> prevContent = (handler == null ? statementHandlers.pop() : handler).getContent(false); if (cases.isEmpty() && !inDefault) { } else { if (inDefault) defaultContents.addAll(prevContent); else{ caseContents.add(prevContent); } } } public void gotDefault() { storePrevCode(null); inDefault = true; defaultContents = new ArrayList<>(); withStatement(newHandler()); } } private class ForHandler { private String type; private final List<String> vars = new ArrayList<>(); private final List<Expression> inits = new ArrayList<>(); private boolean isEach; private Expression eachVar; private Expression post; private Expression condition; public void gotType(String type, List<Modifier> modifiers) { this.type = type; modifiers.removeIf(t -> t.isKeyword("final")); warnUnsupportedModifiers("for-loop", modifiers); } public void gotName(String name) { this.vars.add(name); this.inits.add(null); } public void gotEach(Expression e) { isEach = true; eachVar = e; } public void gotVarInit(Expression e) { this.inits.set(this.vars.size() - 1, e); } public List end(List<CodeElement> content) { if (isEach) return Arrays.asList(new ForeachElement(null, new TypeSlotFragment(type, type), new NameDefSlotFragment(vars.get(0)), eachVar.toFilled(), content, true)); else if (type != null && type.equals("int") && vars.size() == 1 && inits.size() == 1 && inits.get(0).isIntegerLiteral() && condition != null && condition.lessThanIntegerLiteral(vars.get(0)) && post != null && post.isIncrementByOne(vars.get(0))) { String lowerBound = inits.get(0).getJava(); String upperBound = condition.getUpperBound(); return Collections.singletonList(new ForeachElement(null, new TypeSlotFragment("int", "int"), new NameDefSlotFragment(vars.get(0)), new FilledExpressionSlotFragment(lowerBound + ".." + upperBound, "lang.stride.Utility.makeRange(" + lowerBound + ", " + upperBound + ")"), content, true )); } else { List<CodeElement> initAndLoop = new ArrayList<>(); for (int i = 0; i < vars.size(); i++) { initAndLoop.add(new VarElement(null, null, false, false, toType(type), new NameDefSlotFragment(vars.get(i)), inits.get(i) == null ? null : inits.get(i).toFilled(), true)); } List<CodeElement> loopBody = new ArrayList<>(content); if (post != null) loopBody.add(post.toStatement()); initAndLoop.add(new WhileElement(null, condition != null ? condition.toFilled() : new FilledExpressionSlotFragment("true", "true"), loopBody, true)); return initAndLoop; } } public void gotPost(Expression e) { this.post = e; } public void gotCondition(Expression e) { this.condition = e; } }
| A class to handle statements/declarations when we have seen them. | Can be used for single items or for blocks (see constructor). | private abstract class StatementHandler {
| The list of items seen. | private final List<CodeElement> content = new ArrayList<>();
| The list of comments we have seen since they were last dealt with. | Each item includes it's /* * / (space here to avoid ending this comment!) or // delimiters | The list gets cleared once the comments have been dealt with. | private final List<LocatableToken> comments = new ArrayList<>(); private final boolean expectingSingle;
| Constructs a statement handler | @param expectingSingle Whether we expect one call of foundStatement, | or several until we are manually stopped. There are various contexts: | - A for-loop, while-loop, if-statement, etc. In this case | you may find a single statement, or you may find a block, | but the block will get parsed by beginBlockStmtBody which | will install a further StatementHandler to collect the block. | So you put an outer new StatementHandler(true) [i.e. expectingSingle=true] | on the stack. If it's a single statement, we will get one | statement and finish. If it's a block, the inner StatementHandler(false) | [expectingSingle=false) will collect it and pass it to us as one | list, and we finish. | - A block has begun. This might be in beginStmtBlockBody, or | where we know a block occurs (e.g. try-statement, class definition). | In this case, pass expectingSingle=false because we know we are in | a block. You may need to manually call endBlock yourself in this case. | public StatementHandler(boolean expectingSingle) { this.expectingSingle = expectingSingle; if (!statementHandlers.isEmpty()) { StatementHandler prev = statementHandlers.peek(); int curPosition = getCurPosition(); Predicate<LocatableToken> afterCurPosition = t -> t.getPosition() >= curPosition; comments.addAll(prev.comments.stream().filter(afterCurPosition).collect(Collectors.toList())); prev.comments.removeIf(afterCurPosition); } } public final void foundStatement(List<CodeElement> statements) { CommentElement el = collateComments(false); if (el != null) content.add(el); content.addAll(statements); if (!expectingSingle) withStatement(this); else{ endBlock(); } } public final List getContent(boolean eof) { CommentElement el = collateComments(eof); if (el != null) content.add(el); if (!comments.isEmpty()) { comments.forEach(statementHandlers.peek()::gotComment); } return content; } public final void gotComment(LocatableToken token) { comments.add(token); } private CommentElement collateComments(boolean eof) { int curPosition = getCurPosition(); Predicate<LocatableToken> behindCurPosition = t -> eof || t.getPosition() < curPosition; if (!comments.stream().anyMatch(behindCurPosition)) return null; CommentElement el = new CommentElement(comments.stream().filter(behindCurPosition).map(LocatableToken::getText).map(JavaStrideParser::processComment).collect(Collectors.joining(" "))); comments.removeIf(behindCurPosition); return el; } private int getCurPosition() { return (int) Optional.ofNullable(getTokenStream().getMostRecent()).map(LocatableToken::getPosition).orElse(0); }
| When endBlock is called, this StatementHandler will usually just have been removed from the | stack of handlers. You should use this to deal with the results of the collected block | (call getContent to get them). | public abstract void endBlock(); public final String getJavadoc() { if (!comments.isEmpty() && comments.get(comments.size() - 1).getText().startsWith("/**")) { return processComment(comments.remove(comments.size() - 1).getText()); } return null; } public List stealComments() { return Stream.of(collateComments(false)).filter(c -> c != null).collect(Collectors.toList()); } }
| A class keeping track of an if/else-if/else block being put together. | private class IfBuilder { private final ArrayList<List<CodeElement>> blocks = new ArrayList<>(); private final ArrayList<FilledExpressionSlotFragment> conditions = new ArrayList<>(); public IfBuilder(Expression condition) { this.conditions.add(condition.toFilled()); } public void addCondBlock() { withStatement(new StatementHandler(true) { @Override public void endBlock() { blocks.add(getContent(false)); } }); } public void addElseIf() { withExpression(e -> conditions.add(e.toFilled())); } public void endIf() { JavaStrideParser.this.foundStatement(new IfElement(null, conditions.get(0), blocks.get(0), conditions.subList(1, conditions.size()), blocks.subList(1, conditions.size()), blocks.size() > conditions.size() ? blocks.get(blocks.size() - 1) : null, true )); } } @Override protected void beginWhileLoop(LocatableToken token) { super.beginWhileLoop(token); withExpression(exp -> { withStatement(new StatementHandler(true) { @Override public void endBlock() { JavaStrideParser.this.foundStatement(new WhileElement(null, exp.toFilled(), getContent(false), true)); } }); }); } @Override protected void beginIfStmt(LocatableToken token) { super.beginIfStmt(token); withExpression(exp -> { ifHandlers.add(new IfBuilder(exp)); }); } @Override protected void beginIfCondBlock(LocatableToken token) { super.beginIfCondBlock(token); ifHandlers.peek().addCondBlock(); } @Override protected void gotElseIf(LocatableToken token) { super.gotElseIf(token); ifHandlers.peek().addElseIf(); } @Override protected void endIfStmt(LocatableToken token, boolean included) { super.endIfStmt(token, included); ifHandlers.pop().endIf(); } @Override protected void gotReturnStatement(boolean hasValue) { super.gotReturnStatement(hasValue); if (hasValue) withExpression(exp -> foundStatement(new ReturnElement(null, exp.toOptional(), true))); else{ foundStatement(new ReturnElement(null, null, true)); } } @Override protected void gotEmptyStatement() { super.gotEmptyStatement(); foundStatements(Collections.emptyList()); } @Override protected void gotStatementExpression() { super.gotStatementExpression(); withExpression(e -> foundStatement(e.toStatement())); } @Override protected void beginExpression(LocatableToken token) { super.beginExpression(token); if (!expressionHandlers.isEmpty()) expressionHandlers.peek().expressionBegun(token); } @Override protected void endExpression(LocatableToken token, boolean emptyExpression) { super.endExpression(token, emptyExpression); if (!expressionHandlers.isEmpty()) { if (expressionHandlers.peek().expressionEnd(token)) expressionHandlers.pop(); } } @Override protected void gotBinaryOperator(LocatableToken token) { super.gotBinaryOperator(token); if (!expressionHandlers.isEmpty()) { expressionHandlers.peek().binaryOperator(token); } } @Override protected void gotUnaryOperator(LocatableToken token) { super.gotUnaryOperator(token); if (!expressionHandlers.isEmpty()) { expressionHandlers.peek().unaryOperator(token); } } @Override protected void gotPostOperator(LocatableToken token) { super.gotPostOperator(token); if (!expressionHandlers.isEmpty()) { expressionHandlers.peek().postOperator(token); } } @Override protected void beginStmtblockBody(LocatableToken token) { super.beginStmtblockBody(token); withStatement(new StatementHandler(false) { @Override public void endBlock() { foundStatements(getContent(false)); } }); } @Override protected void endStmtblockBody(LocatableToken token, boolean included) { super.endStmtblockBody(token, included); statementHandlers.pop().endBlock(); } @Override protected void beginThrows(LocatableToken token) { super.beginThrows(token); typeHandlers.push(type -> methods.peek().throwsTypes.add(type)); } @Override protected void endThrows() { super.endThrows(); typeHandlers.pop(); } @Override protected void gotMethodTypeParamsBegin() { super.gotMethodTypeParamsBegin(); warnings.add(new UnsupportedFeature("generic methods")); } @Override protected void gotConstructorDecl(LocatableToken token, LocatableToken hiddenToken) { super.gotConstructorDecl(token, hiddenToken); methods.push(new MethodBuilder(null, null, modifiers.peek(), statementHandlers.peek().getJavadoc())); } @Override protected void gotMethodDeclaration(LocatableToken nameToken, LocatableToken hiddenToken) { super.gotMethodDeclaration(nameToken, hiddenToken); methods.push(new MethodBuilder(prevTypes.pop(), nameToken.getText(), modifiers.peek(), statementHandlers.peek().getJavadoc())); } @Override protected void beginMethodBody(LocatableToken token) { super.beginMethodBody(token); methods.peek().hasBody = true; withStatement(new StatementHandler(false) { @Override public void endBlock() { } }); } @Override protected void endMethodDecl(LocatableToken token, boolean included) { super.endMethodDecl(token, included); MethodBuilder details = methods.pop(); List<CodeElement> body = details.hasBody ? statementHandlers.pop().getContent(false) : null; String name = details.name; List<ThrowsTypeFragment> throwsTypes = details.throwsTypes.stream().map(t -> new ThrowsTypeFragment(toType(t))).collect(Collectors.toList()); List<Modifier> modifiers = details.modifiers; AccessPermission permission = removeAccess(modifiers, AccessPermission.PROTECTED); if (name != null) { boolean _final = modifiers.removeIf(t -> t.isKeyword("final")); boolean _static = modifiers.removeIf(t -> t.isKeyword("static")); modifiers.removeIf(t -> t.isKeyword("abstract")); modifiers.removeIf(t -> t.isAnnotation("@Override")); warnUnsupportedModifiers("method", modifiers); String type = details.type; if (details.hasBody) foundStatement(new NormalMethodElement(null, new AccessPermissionFragment(permission), _static, _final, toType(type), new NameDefSlotFragment(name), details.parameters, throwsTypes, body, new JavadocUnit(details.comment), true)); else{ foundStatement(new MethodProtoElement(null, toType(type), new NameDefSlotFragment(name), details.parameters, throwsTypes, new JavadocUnit(details.comment), true)); } } else { warnUnsupportedModifiers("method", modifiers); SuperThis delegate = SuperThis.fromString(details.constructorCall); Expression delegateArgs = delegate == null ? null : new Expression(details.constructorArgs, " , ", warnings::add); foundStatement(new ConstructorElement(null, new AccessPermissionFragment(permission), details.parameters, throwsTypes, delegate == null ? null : new SuperThisFragment(delegate), delegateArgs == null ? null : delegateArgs.toSuperThis(), body, new JavadocUnit(details.comment), true)); } } private static TypeSlotFragment toType(String t) { if (t == null) return null; else{ return new TypeSlotFragment(t, t); } } private void warnUnsupportedModifiers(String context, List<Modifier> modifiers) { modifiers.forEach(t -> warnings.add(new ConversionWarning.UnsupportedModifier(context, t.toString()))); } private static AccessPermission removeAccess(List<Modifier> modifiers, AccessPermission defaultAccess) { AccessPermission permission = defaultAccess; if (modifiers.removeIf(t -> t.isKeyword("private"))) permission = AccessPermission.PRIVATE; if (modifiers.removeIf(t -> t.isKeyword("protected"))) permission = AccessPermission.PROTECTED; if (modifiers.removeIf(t -> t.isKeyword("public"))) permission = AccessPermission.PUBLIC; return permission; } @Override protected void gotTypeSpec(List<LocatableToken> tokens) { super.gotTypeSpec(tokens); String type = tokens.stream().map(LocatableToken::getText).collect(Collectors.joining()); if (!typeHandlers.isEmpty()) typeHandlers.peek().accept(type); else{ prevTypes.add(type); } } @Override protected void gotMethodParameter(LocatableToken token, LocatableToken ellipsisToken) { super.gotMethodParameter(token, ellipsisToken); if (ellipsisToken != null) warnings.add(new ConversionWarning.UnsupportedFeature("varargs")); String type = prevTypes.pop(); methods.peek().parameters.add(new ParamFragment(toType(type), new NameDefSlotFragment(token.getText()))); } @Override protected void gotConstructorCall(LocatableToken token) { super.gotConstructorCall(token); MethodBuilder method = methods.peek(); method.constructorCall = token.getText(); expressionHandlers.pop(); withExpression(e -> { }); withArgumentList(args -> { method.constructorArgs = args; }); } @Override protected void gotDeclBegin(LocatableToken token) { super.gotDeclBegin(token); modifiers.push(new ArrayList<>()); } @Override protected void beginFormalParameter(LocatableToken token) { super.beginFormalParameter(token); modifiers.push(new ArrayList<>()); } @Override protected void modifiersConsumed() { super.modifiersConsumed(); modifiers.pop(); } @Override protected void gotModifier(LocatableToken token) { super.gotModifier(token); if (!modifiers.isEmpty()) modifiers.peek().add(new Modifier.KeywordModifier(token)); } @Override protected void gotAnnotation(List<LocatableToken> annName, boolean paramsFollow) { super.gotAnnotation(annName, paramsFollow); if (!modifiers.isEmpty()) { Modifier.AnnotationModifier ann = new Modifier.AnnotationModifier(annName); modifiers.peek().add(ann); if (paramsFollow) withArgumentList(exps -> ann.setParams(exps)); } } @Override protected void beginFieldDeclarations(LocatableToken first) { super.beginFieldDeclarations(first); curField.push(new FieldOrVarBuilder(prevTypes.pop(), modifiers.peek())); } @Override protected void gotField(LocatableToken first, LocatableToken idToken, boolean initExpressionFollows) { super.gotField(first, idToken, initExpressionFollows); handleFieldOrVar(idToken, initExpressionFollows, AccessPermission.PROTECTED); } @Override protected void gotVariableDecl(LocatableToken first, LocatableToken idToken, boolean inited) { super.gotVariableDecl(first, idToken, inited); curField.push(new FieldOrVarBuilder(prevTypes.pop(), modifiers.peek())); handleFieldOrVar(idToken, inited, null); } @Override protected void gotArrayDeclarator() { super.gotArrayDeclarator(); if (!prevTypes.isEmpty()) prevTypes.push(prevTypes.pop() + "[]"); } private void handleFieldOrVar(LocatableToken idToken, boolean initExpressionFollows, AccessPermission defaultAccess) { FieldOrVarBuilder details = curField.peek(); List<Modifier> modifiers = new ArrayList<>(details.modifiers); AccessPermission permission = removeAccess(modifiers, defaultAccess); boolean _final = modifiers.removeIf(t -> t.isKeyword("final")); boolean _static = modifiers.removeIf(t -> t.isKeyword("static")); warnUnsupportedModifiers("variable", modifiers); Consumer<Expression> handler = e -> foundStatement(new VarElement(null, permission == null ? null : new AccessPermissionFragment(permission), _static, _final, toType(details.type), new NameDefSlotFragment(idToken.getText()), e == null ? null : e.toFilled(), true)); if (initExpressionFollows) withExpression(handler); else{ handler.accept(null); } } @Override protected void gotSubsequentField(LocatableToken first, LocatableToken idToken, boolean initFollows) { super.gotSubsequentField(first, idToken, initFollows); handleFieldOrVar(idToken, initFollows, AccessPermission.PROTECTED); } @Override protected void gotSubsequentVar(LocatableToken first, LocatableToken idToken, boolean inited) { super.gotSubsequentVar(first, idToken, inited); handleFieldOrVar(idToken, inited, null); } @Override protected void endFieldDeclarations(LocatableToken token, boolean included) { super.endFieldDeclarations(token, included); curField.pop(); } @Override protected void gotTopLevelDecl(LocatableToken token) { super.gotTopLevelDecl(token); withTypeDef(td -> foundStatement(td), false); } @Override protected void gotInnerType(LocatableToken start) { super.gotInnerType(start); withTypeDef(inner -> { }, true); warnings.add(new UnsupportedFeature("inner " + start.getText())); } @Override protected void gotTypeDef(LocatableToken firstToken, int tdType) { super.gotTypeDef(firstToken, tdType); if (tdType == TYPEDEF_EPIC_FAIL) return; typeDefHandlers.peek().typeDefBegun(firstToken); List<Modifier> modifiers = this.modifiers.peek(); switch (tdType) { case TYPEDEF_CLASS: typeDefHandlers.peek().startedClass(modifiers, statementHandlers.peek().getJavadoc()); break; case TYPEDEF_INTERFACE: typeDefHandlers.peek().startedInterface(modifiers, statementHandlers.peek().getJavadoc()); break; case TYPEDEF_ANNOTATION: warnings.add(new UnsupportedFeature("annotation")); break; case TYPEDEF_ENUM: warnings.add(new UnsupportedFeature("enum")); break; default: throw new ParseFailure("Typedef parse failure"); } } @Override protected void gotTypeDefEnd(LocatableToken token, boolean included) { super.gotTypeDefEnd(token, included); if (!typeDefHandlers.isEmpty()) { typeDefHandlers.pop().typeDefEnd(token); } } @Override protected void beginTypeDefExtends(LocatableToken extendsToken) { super.beginTypeDefExtends(extendsToken); typeHandlers.push(type -> { typeDefHandlers.peek().typeDefExtends(type); }); } @Override protected void endTypeDefExtends() { super.endTypeDefExtends(); typeHandlers.pop(); } @Override protected void beginTypeDefImplements(LocatableToken implementsToken) { super.beginTypeDefImplements(implementsToken); typeHandlers.push(type -> { typeDefHandlers.peek().typeDefImplements(type); }); } @Override protected void endTypeDefImplements() { super.endTypeDefImplements(); typeHandlers.pop(); } @Override protected void gotTypeDefName(LocatableToken nameToken) { super.gotTypeDefName(nameToken); if (!typeDefHandlers.isEmpty()) typeDefHandlers.peek().gotName(nameToken.getText()); } @Override protected void beginTypeBody(LocatableToken leftCurlyToken) { super.beginTypeBody(leftCurlyToken); withStatement(new StatementHandler(false) { @Override public void endBlock() { } }); } @Override protected void endTypeBody(LocatableToken endCurlyToken, boolean included) { super.endTypeBody(endCurlyToken, included); List<CodeElement> content = statementHandlers.pop().getContent(false); if (!typeDefHandlers.isEmpty()) typeDefHandlers.peek().gotContent(content); } @Override protected void gotPackage(List<LocatableToken> pkgTokens) { super.gotPackage(pkgTokens); this.pkg = pkgTokens.stream().map(LocatableToken::getText).collect(Collectors.joining()); } @Override public void gotComment(LocatableToken token) { super.gotComment(token); statementHandlers.peek().gotComment(token); if (!expressionHandlers.isEmpty()) { expressionHandlers.forEach(handler -> { handler.beginMask(token); handler.endMask(token); }); } } private static String processComment(String comment) { if (comment.startsWith("//")) comment = comment.substring(2).trim(); else{ comment = JavaUtils.javadocToString(comment).trim(); } comment = Arrays.stream(Utility.split(comment, System.getProperty("line.separator"))) .map(String::trim) .reduce((a, b) -> { a = a.isEmpty() ? "\n" : a; if (a.endsWith("\n")) return a + (b.isEmpty() ? "\n" : b); else if (b.isEmpty()) return a + "\n"; else{ return a + " " + b; } }).orElse(""); return comment; } @Override protected void gotBreakContinue(LocatableToken keywordToken, LocatableToken labelToken) { super.gotBreakContinue(keywordToken, labelToken); if (keywordToken.getType() == JavaTokenTypes.LITERAL_break) { foundStatement(new BreakElement(null, true)); if (labelToken != null) warnings.add(new ConversionWarning.UnsupportedFeature("break label")); } else { warnings.add(new ConversionWarning.UnsupportedFeature(keywordToken.getText())); } } @Override protected void gotThrow(LocatableToken token) { super.gotThrow(token); withExpression(e -> foundStatement(new ThrowElement(null, e.toFilled(), true))); } @Override protected void beginTryCatchSmt(LocatableToken token, boolean hasResource) { super.beginTryCatchSmt(token, hasResource); if (hasResource) warnings.add(new ConversionWarning.UnsupportedFeature("try-with-resource")); tries.push(new TryBuilder()); } @Override protected void beginTryBlock(LocatableToken token) { super.beginTryBlock(token); withStatement(new StatementHandler(false) { @Override public void endBlock() { tries.peek().tryContent.addAll(getContent(false)); } }); } @Override protected void endTryBlock(LocatableToken token, boolean included) { super.endTryBlock(token, included); statementHandlers.pop().endBlock(); } @Override protected void gotCatchFinally(LocatableToken token) { super.gotCatchFinally(token); if (token.getType() == JavaTokenTypes.LITERAL_catch) tries.peek().catchTypes.push(new ArrayList<>()); else{ withStatement(new StatementHandler(true){ @Override public void endBlock(){ tries.peek().finallyContents = new ArrayList<>(getContent(false)); } } }); } @Override protected void gotCatchVarName(LocatableToken token) { super.gotCatchVarName(token); tries.peek().catchNames.add(token.getText()); tries.peek().catchTypes.peek().add(prevTypes.pop()); withStatement(new StatementHandler(true) { @Override public void endBlock() { tries.peek().catchBlocks.add(getContent(false)); } }); } @Override protected void gotMultiCatch(LocatableToken token) { super.gotMultiCatch(token); tries.peek().catchTypes.peek().add(prevTypes.pop()); } @Override protected void endTryCatchStmt(LocatableToken token, boolean included) { super.endTryCatchStmt(token, included); TryBuilder details = tries.pop(); List<TypeSlotFragment> catchTypes = new ArrayList<>(); List<NameDefSlotFragment> catchNames = new ArrayList<>(); List<List<CodeElement>> catchBlocks = new ArrayList<>(); for (int i = 0; i < details.catchNames.size(); i++) { final int iFinal = i; details.catchTypes.get(i).forEach(type -> { catchTypes.add(new TypeSlotFragment(type, type)); catchNames.add(new NameDefSlotFragment(details.catchNames.get(iFinal))); catchBlocks.add(new ArrayList<>(details.catchBlocks.get(iFinal))); }); } foundStatement(new TryElement(null, details.tryContent, catchTypes, catchNames, catchBlocks, details.finallyContents, true)); } @Override protected void gotImport(List<LocatableToken> tokens, boolean isStatic, LocatableToken importToken, LocatableToken semiColonToken) { super.gotImport(tokens, isStatic, importToken, semiColonToken); imports.add(tokens.stream().map(LocatableToken::getText).collect(Collectors.joining())); } @Override protected void gotWildcardImport(List<LocatableToken> tokens, boolean isStatic, LocatableToken importToken, LocatableToken semiColonToken) { super.gotWildcardImport(tokens, isStatic, importToken, semiColonToken); imports.add(tokens.stream().map(LocatableToken::getText).collect(Collectors.joining()) + ".*"); } @Override protected void beginSwitchStmt(LocatableToken token) { super.beginSwitchStmt(token); switchHandlers.push(new SwitchHandler()); withExpression(e -> switchHandlers.peek().gotSwitchExpression(e)); } @Override protected void beginSwitchBlock(LocatableToken token) { super.beginSwitchBlock(token); switchHandlers.peek().beginBlock(); } @Override protected void gotSwitchCase() { super.gotSwitchCase(); withExpression(e -> switchHandlers.peek().gotCase(e)); } @Override protected void gotSwitchDefault() { super.gotSwitchDefault(); switchHandlers.peek().gotDefault(); } @Override protected void endSwitchBlock(LocatableToken token) { super.endSwitchBlock(token); statementHandlers.pop().endBlock(); } @Override protected void beginForLoop(LocatableToken token) { super.beginForLoop(token); forHandlers.push(new ForHandler()); modifiers.push(new ArrayList<>()); } @Override protected void gotForInit(LocatableToken first, LocatableToken idToken) { super.gotForInit(first, idToken); forHandlers.peek().gotType(prevTypes.pop(), modifiers.peek()); forHandlers.peek().gotName(idToken.getText()); } @Override protected void gotSubsequentForInit(LocatableToken first, LocatableToken idToken, boolean initFollows) { super.gotSubsequentForInit(first, idToken, initFollows); forHandlers.peek().gotName(idToken.getText()); if (initFollows) withExpression(e -> forHandlers.peek().gotVarInit(e)); } @Override protected void determinedForLoop(boolean forEachLoop, boolean initFollows) { super.determinedForLoop(forEachLoop, initFollows); if (forEachLoop) { withExpression(e -> forHandlers.peek().gotEach(e)); } else if (initFollows) { withExpression(e -> forHandlers.peek().gotVarInit(e)); } } @Override protected void gotForIncrement(boolean isPresent) { super.gotForIncrement(isPresent); if (isPresent) withExpression(e -> forHandlers.peek().gotPost(e)); } @Override protected void gotForTest(boolean isPresent) { super.gotForTest(isPresent); if (isPresent) withExpression(e -> forHandlers.peek().gotCondition(e)); } @Override protected void beginForLoopBody(LocatableToken token) { super.beginForLoopBody(token); withStatement(new StatementHandler(true) { @Override public void endBlock() { JavaStrideParser.this.foundStatements(forHandlers.pop().end(getContent(false))); } }); } @Override protected void beginArgumentList(LocatableToken token) { super.beginArgumentList(token); if (!argumentHandlers.isEmpty()) argumentHandlers.peek().argumentListBegun(); } @Override protected void endArgumentList(LocatableToken token) { super.endArgumentList(token); if (!argumentHandlers.isEmpty()) argumentHandlers.peek().argumentListEnd(); } @Override protected void endArgument() { super.endArgument(); if (!argumentHandlers.isEmpty()) argumentHandlers.peek().gotArgument(); } @Override protected void gotAssert() { super.gotAssert(); warnings.add(new UnsupportedFeature("assert")); } @Override protected void beginSynchronizedBlock(LocatableToken token) { super.beginSynchronizedBlock(token); warnings.add(new UnsupportedFeature("synchronized")); } @Override protected void beginInitBlock(LocatableToken first, LocatableToken lcurly) { super.beginInitBlock(first, lcurly); warnings.add(new UnsupportedFeature("initializer block")); withStatement(new StatementHandler(false) { @Override public void endBlock() { } }); } @Override protected void endInitBlock(LocatableToken rcurly, boolean included) { super.endInitBlock(rcurly, included); statementHandlers.pop(); } @Override protected void beginAnonClassBody(LocatableToken token, boolean isEnumMember) { super.beginAnonClassBody(token, isEnumMember); beginExpressionMask(token); warnings.add(new UnsupportedFeature("anonymous class")); withStatement(new StatementHandler(false) { @Override public void endBlock() { } }); } private void beginExpressionMask(LocatableToken from) { if (!expressionHandlers.isEmpty()) expressionHandlers.peek().beginMask(from); } private void endExpressionMask(LocatableToken from) { if (!expressionHandlers.isEmpty()) expressionHandlers.peek().endMask(from); } @Override protected void endAnonClassBody(LocatableToken token, boolean included) { super.endAnonClassBody(token, included); statementHandlers.pop(); endExpressionMask(token); } @Override protected void gotLambdaFormalName(LocatableToken name) { super.gotLambdaFormalName(name); warnUnsupportedModifiers("lambda parameter", modifiers.peek()); modifiers.peek().forEach(mod -> { expressionHandlers.peek().beginMask(mod.getStart()); expressionHandlers.peek().endMask(mod.getEnd()); }); } @Override protected void gotLambdaFormalParam() { super.gotLambdaFormalParam(); modifiers.push(new ArrayList<>()); } @Override protected void gotLambdaFormalType(List<LocatableToken> tokens) { super.gotLambdaFormalType(tokens); warnings.add(new UnsupportedFeature("lambda parameter type")); expressionHandlers.peek().beginMask(tokens.get(0)); expressionHandlers.peek().endMask(tokens.get(tokens.size() - 1)); } @Override protected void beginLambda(boolean lambdaIsBlock, LocatableToken openCurly) { super.beginLambda(lambdaIsBlock, openCurly); if (lambdaIsBlock) { warnings.add(new UnsupportedFeature("lambda block")); beginExpressionMask(openCurly); withStatement(new StatementHandler(true) { @Override public void endBlock() { } }); } } @Override protected void endLambda(LocatableToken closeCurly) { super.endLambda(closeCurly); if (closeCurly != null) endExpressionMask(closeCurly); } @Override protected void gotQuestionColon(LocatableToken token) { super.gotQuestionColon(token); expressionHandlers.peek().beginMask(token); expressionHandlers.peek().endMask(token); } @Override protected void gotQuestionOperator(LocatableToken token) { super.gotQuestionOperator(token); warnings.add(new UnsupportedFeature("conditional operator (.. ? .. : ..)")); expressionHandlers.peek().beginMask(token); expressionHandlers.peek().endMask(token); } private String getText(LocatableToken start, LocatableToken endExcl, List<Mask> masks) { if (masks.isEmpty()) return source.substring(start.getPosition(), endExcl.getPosition()); else { int prev = start.getPosition(); StringBuilder r = new StringBuilder(); for (Mask m : masks) { if (m.getStart().getPosition() >= prev && m.getEnd().getPosition() <= endExcl.getPosition()) { r.append(source.substring(prev, m.getStart().getPosition())); prev = m.getEnd().getPosition() + m.getEnd().getLength(); } } r.append(source.substring(prev, endExcl.getPosition())); return r.toString(); } }
| Passes the next complete expression to the handler. | | This will consume the next outermost expression. Inner expressions | will be ignored unless another handler is installed in the mean-time. | | E.g. Let's say you call withExpression(h). Then you parse: | 0+(1+2)+3; | | The 0 will be the start of the outermost expression. The 1 will | also begin an expression, but this handler will just ignore | the fact that there was an inner expression, and will wait | until the 3 which ends the expression, and will pass | "0+(1+2)+3" to the handler. It will not pass "1+2". |* * @param handler The callback for the next outermost expression. */ private void withExpression(Consumer<Expression> handler) { expressionHandlers.push(new ExpressionBuilder(handler, this::getText, warnings::add)); | |} | |// A delegate for our TypeDefHandler implementation | |private static interface TypeDefDelegate | |{ | |public void gotName(String name); | |public CodeElement end(); | |public void gotContent(CodeElement element); | |public defVis void gotImplements(String type); | |public defVis void gotExtends(String type); | |} | |private class InterfaceDelegate implements TypeDefDelegate | |{ | |private final List<Modifier> modifiers; | |private final String doc; | |private String name; | |private final List<CodeElement> fields = new ArrayList<>(); | |private final List<CodeElement> methods = new ArrayList<>(); | |private final List<CommentElement> pendingComments = new ArrayList<>(); | |private final List<String> extendsTypes = new ArrayList<>(); | |public InterfaceDelegate(List<Modifier> modifiers, String doc) | |{ | |this.modifiers = new ArrayList<>(modifiers); | |this.doc = doc; | |} | |@Override | |public void gotName(String name) | |{ | |this.name = name; | |} | |@Override | |public void gotExtends(String type) | |{ | |extendsTypes.add(type); | |} | |@Override | |public void gotImplements(String type) | |{ | |} | |@Override | |public void gotContent(CodeElement element) | |{ | |if (element instanceof VarElement) | |{ | |fields.addAll(pendingComments); | |fields.add(element); | |} | |public defVis else if (element instanceof MethodProtoElement) | |{ | |methods.addAll(pendingComments); | |methods.add(element); | |} | |public defVis else if (element instanceof CommentElement) | |{ | |pendingComments.add((CommentElement)element); | |return; | |} | |else | |{ | |warnings.add(new ConversionWarning.UnsupportedFeature(element.getClass().toString()), t -> pendingComments.add(new CommentElement(processComment(t.getText())))); | |return; | |} | |pendingComments.clear(); | |} | |@Override | |public CodeElement end() | |{ | |if (!methods.isEmpty()) | |methods.addAll(pendingComments); | |else{ fields.addAll(pendingComments); | |} | |pendingComments.clear(); | |// Public is the default so don't warn it's unsupported: | |modifiers.removeIf(t -> t.isKeyword("public")); warnUnsupportedModifiers("interface", modifiers); return new InterfaceElement(null, null, new NameDefSlotFragment(name), extendsTypes.stream().map(t -> toType(t)).collect(Collectors.toList()), fields, methods, | |new JavadocUnit(doc), pkg == null ? null : pkg, importsForCU(), true); | |} | |} | |private class ClassDelegate implements TypeDefDelegate | |{ | |private final List<Modifier> modifiers; | |private final String doc; | |private String name; | |private final List<CodeElement> fields = new ArrayList<>(); | |private final List<CodeElement> constructors = new ArrayList<>(); | |private final List<CodeElement> methods = new ArrayList<>(); | |private final List<CommentElement> pendingComments = new ArrayList<>(); | |private String extendsType; | |private final List<String> implementsTypes = new ArrayList<>(); | |public ClassDelegate(List<Modifier> modifiers, String doc) | |{ | |this.modifiers = new ArrayList<>(modifiers); | |this.doc = doc; | |} | |@Override | |public void gotName(String name) | |{ | |this.name = name; | |} | |@Override | |public void gotExtends(String type) | |{ | |extendsType = type; | |} | |@Override | |public void gotImplements(String type) | |{ | |implementsTypes.add(type); | |} | |@Override | |public void gotContent(CodeElement element) | |{ | |if (element instanceof VarElement) | |{ | |fields.addAll(pendingComments); | |fields.add(element); | |} | |public defVis else if (element instanceof ConstructorElement) | |{ | |constructors.addAll(pendingComments); | |constructors.add(element); | |} | |public defVis else if (element instanceof NormalMethodElement || element instanceof MethodProtoElement) | |{ | |methods.addAll(pendingComments); | |methods.add(element); | |} | |public defVis else if (element instanceof CommentElement) | |{ | |pendingComments.add((CommentElement)element); | |return; | |} | |else | |{ | |warnings.add(new ConversionWarning.UnsupportedFeature(element.getClass().toString()), t -> pendingComments.add(new CommentElement(processComment(t.getText())))); | |return; | |} | |pendingComments.clear(); | |} | |@Override | |public CodeElement end() | |{ | |if (!methods.isEmpty()) | |methods.addAll(pendingComments); | |else if (!constructors.isEmpty()) | |constructors.addAll(pendingComments); | |else{ fields.addAll(pendingComments); | |} | |pendingComments.clear(); | |boolean _abstract = modifiers.removeIf(t -> t.isKeyword("abstract")); // Public is the default so don't warn it's unsupported: modifiers.removeIf(t -> t.isKeyword("public")); warnUnsupportedModifiers("class", modifiers); return new ClassElement(null, null, _abstract, new NameDefSlotFragment(name), toType(extendsType), implementsTypes.stream().map(t -> toType(t)).collect(Collectors.toList()), fields, | |constructors, methods, | |new JavadocUnit(doc), pkg == null ? null : pkg, importsForCU(), true); | |} | |} | |/** | Gets the list of ImportElements found when processing this compilation unit. | Any import of lang.stride.* will be ignored because that is already implicit in Stride. | (This can happen in particular when you convert Stride to Java and back again) | private List importsForCU() { return imports.stream() .filter(imp -> !imp.equals("lang.stride.*")) .map(imp -> new ImportElement(imp, null, true)) .collect(Collectors.toList()); } private void withTypeDef(Consumer<CodeElement> handler, boolean inner) { typeDefHandlers.push(new TypeDefHandler() { TypeDefDelegate delegate = null; @Override public void typeDefBegun(LocatableToken start) { } @Override public void typeDefEnd(LocatableToken end) { if (delegate != null) { handler.accept(delegate.end()); } } @Override public void startedClass(List<Modifier> modifiers, String doc) { delegate = new ClassDelegate(inner ? Collections.emptyList() : modifiers, doc); if (!inner) statementHandlers.peek().stealComments().forEach(delegate::gotContent); } @Override public void startedInterface(List<Modifier> modifiers, String doc) { delegate = new InterfaceDelegate(inner ? Collections.emptyList() : modifiers, doc); if (!inner) statementHandlers.peek().stealComments().forEach(delegate::gotContent); } @Override public void gotName(String name) { if (delegate != null) delegate.gotName(name); } @Override public void gotContent(List<CodeElement> content) { if (delegate != null) content.forEach(delegate::gotContent); } @Override public void typeDefImplements(String type) { if (delegate != null) delegate.gotImplements(type); } @Override public void typeDefExtends(String type) { if (delegate != null) delegate.gotExtends(type); } }); } private void withStatement(StatementHandler handler) { statementHandlers.push(handler); } private class ArgumentListHandler { private final List<Expression> args = new ArrayList<>(); private int outstanding = 0; private final Consumer<List<Expression>> argHandler; public ArgumentListHandler(Consumer<List<Expression>> argHandler) { this.argHandler = argHandler; } public void argumentListBegun() { outstanding += 1; if (outstanding == 1) { withExpression(args::add); } } public void gotArgument() { if (outstanding == 1) { withExpression(args::add); } } public void argumentListEnd() { if (outstanding == 1) { expressionHandlers.pop(); argHandler.accept(args); argumentHandlers.pop(); } outstanding -= 1; } } private void withArgumentList(Consumer<List<Expression>> argHandler) { argumentHandlers.push(new ArgumentListHandler(argHandler)); } private void foundStatement(CodeElement statement) { foundStatements(Collections.singletonList(statement)); } private void foundStatements(List<CodeElement> statements) { statementHandlers.pop().foundStatement(statements); } @Override protected void finishedCU(int state) { if (state == 1) { result.foundStatement(Utility.mapList(imports, i -> new ImportElement(i, null, true))); } }
| Gets the overall result of the parse | public List getCodeElements() { return result.getContent(true); } }
top, use, map, class JavaStrideParser

top, use, map, class JavaStrideParser . WarningManager

.   add
.   add
.   endBlock
.   JavaStrideParser
.   getWarnings

top, use, map, class SwitchHandler

.   gotSwitchExpression
.   end
.   beginBlock
.   newHandler
.   endBlock
.   gotCase
.   storePrevCode
.   gotDefault

top, use, map, class ForHandler

.   gotType
.   gotName
.   gotEach
.   gotVarInit
.   end
.   gotPost
.   gotCondition

top, use, map, abstract class StatementHandler

.   StatementHandler
.   foundStatement
.   getContent
.   gotComment
.   collateComments
.   getCurPosition
.   endBlock
.   getJavadoc
.   stealComments

top, use, map, class IfBuilder

.   IfBuilder
.   addCondBlock
.   endBlock
.   addElseIf
.   endIf
.   beginWhileLoop
.   endBlock
.   beginIfStmt
.   beginIfCondBlock
.   gotElseIf
.   endIfStmt
.   gotReturnStatement
.   gotEmptyStatement
.   gotStatementExpression
.   beginExpression
.   endExpression
.   gotBinaryOperator
.   gotUnaryOperator
.   gotPostOperator
.   beginStmtblockBody
.   endBlock
.   endStmtblockBody
.   beginThrows
.   endThrows
.   gotMethodTypeParamsBegin
.   gotConstructorDecl
.   gotMethodDeclaration
.   beginMethodBody
.   endBlock
.   endMethodDecl
.   toType
.   warnUnsupportedModifiers
.   removeAccess
.   gotTypeSpec
.   gotMethodParameter
.   gotConstructorCall
.   gotDeclBegin
.   beginFormalParameter
.   modifiersConsumed
.   gotModifier
.   gotAnnotation
.   beginFieldDeclarations
.   gotField
.   gotVariableDecl
.   gotArrayDeclarator
.   handleFieldOrVar
.   gotSubsequentField
.   gotSubsequentVar
.   endFieldDeclarations
.   gotTopLevelDecl
.   gotInnerType
.   gotTypeDef
.   gotTypeDefEnd
.   beginTypeDefExtends
.   endTypeDefExtends
.   beginTypeDefImplements
.   endTypeDefImplements
.   gotTypeDefName
.   beginTypeBody
.   endBlock
.   endTypeBody
.   gotPackage
.   gotComment
.   processComment
.   gotBreakContinue
.   gotThrow
.   beginTryCatchSmt
.   beginTryBlock
.   endBlock
.   endTryBlock
.   gotCatchFinally
.   endBlock
.   gotCatchVarName
.   endBlock
.   gotMultiCatch
.   endTryCatchStmt
.   gotImport
.   gotWildcardImport
.   beginSwitchStmt
.   beginSwitchBlock
.   gotSwitchCase
.   gotSwitchDefault
.   endSwitchBlock
.   beginForLoop
.   gotForInit
.   gotSubsequentForInit
.   determinedForLoop
.   gotForIncrement
.   gotForTest
.   beginForLoopBody
.   endBlock
.   beginArgumentList
.   endArgumentList
.   endArgument
.   gotAssert
.   beginSynchronizedBlock
.   beginInitBlock
.   endBlock
.   endInitBlock
.   beginAnonClassBody
.   endBlock
.   beginExpressionMask
.   endExpressionMask
.   endAnonClassBody
.   gotLambdaFormalName
.   gotLambdaFormalParam
.   gotLambdaFormalType
.   beginLambda
.   endBlock
.   endLambda
.   gotQuestionColon
.   gotQuestionOperator
.   getText
.   importsForCU
.   withTypeDef
.   typeDefBegun
.   typeDefEnd
.   startedClass
.   startedInterface
.   gotName
.   gotContent
.   typeDefImplements
.   typeDefExtends
.   withStatement

top, use, map, class ArgumentListHandler

.   ArgumentListHandler
.   argumentListBegun
.   gotArgument
.   argumentListEnd
.   withArgumentList
.   foundStatement
.   foundStatements
.   finishedCU
.   getCodeElements




2110 neLoCode + 252 LoComm