use of org.apache.groovy.parser.antlr4.GroovyLexer.FOR in project groovy by apache.
the class AstBuilder method visitSwitchBlockStatementExpressionGroup.
@Override
@SuppressWarnings("unchecked")
public Tuple3<List<Statement>, Boolean, Boolean> visitSwitchBlockStatementExpressionGroup(SwitchBlockStatementExpressionGroupContext ctx) {
int labelCnt = ctx.switchExpressionLabel().size();
List<Token> firstLabelHolder = new ArrayList<>(1);
final int[] arrowCntHolder = new int[1];
boolean[] isArrowHolder = new boolean[1];
boolean[] hasResultStmtHolder = new boolean[1];
List<Statement> result = (List<Statement>) ctx.switchExpressionLabel().stream().map(e -> (Object) this.visitSwitchExpressionLabel(e)).reduce(new ArrayList<Statement>(4), (r, e) -> {
List<Statement> statementList = (List<Statement>) r;
Tuple3<Token, List<Expression>, Integer> tuple = (Tuple3<Token, List<Expression>, Integer>) e;
boolean isArrow = ARROW == tuple.getV3();
isArrowHolder[0] = isArrow;
if (isArrow) {
if (++arrowCntHolder[0] > 1 && !firstLabelHolder.isEmpty()) {
throw createParsingFailedException("`case ... ->` does not support falling through cases", firstLabelHolder.get(0));
}
}
boolean isLast = labelCnt - 1 == statementList.size();
BlockStatement codeBlock = this.visitBlockStatements(ctx.blockStatements());
List<Statement> statements = codeBlock.getStatements();
int statementsCnt = statements.size();
if (0 == statementsCnt) {
throw createParsingFailedException("`yield` is expected", ctx.blockStatements());
}
if (isArrow && statementsCnt > 1) {
throw createParsingFailedException("Expect only 1 statement, but " + statementsCnt + " statements found", ctx.blockStatements());
}
if (!isArrow) {
boolean[] hasYieldHolder = new boolean[1];
boolean[] hasThrowHolder = new boolean[1];
codeBlock.visit(new CodeVisitorSupport() {
@Override
public void visitReturnStatement(ReturnStatement statement) {
if (isTrue(statement, IS_YIELD_STATEMENT)) {
hasYieldHolder[0] = true;
return;
}
super.visitReturnStatement(statement);
}
@Override
public void visitThrowStatement(ThrowStatement statement) {
hasThrowHolder[0] = true;
}
});
if (hasYieldHolder[0] || hasThrowHolder[0]) {
hasResultStmtHolder[0] = true;
}
}
Statement exprOrBlockStatement = statements.get(0);
if (exprOrBlockStatement instanceof BlockStatement) {
BlockStatement blockStatement = (BlockStatement) exprOrBlockStatement;
List<Statement> branchStatementList = blockStatement.getStatements();
if (1 == branchStatementList.size()) {
exprOrBlockStatement = branchStatementList.get(0);
}
}
if (!(exprOrBlockStatement instanceof ReturnStatement || exprOrBlockStatement instanceof ThrowStatement)) {
if (isArrow) {
MethodCallExpression callClosure = callX(configureAST(closureX(null, exprOrBlockStatement), exprOrBlockStatement), "call");
callClosure.setImplicitThis(false);
Expression resultExpr = exprOrBlockStatement instanceof ExpressionStatement ? ((ExpressionStatement) exprOrBlockStatement).getExpression() : callClosure;
codeBlock = configureAST(createBlockStatement(configureAST(returnS(resultExpr), exprOrBlockStatement)), exprOrBlockStatement);
}
}
switch(tuple.getV1().getType()) {
case CASE:
{
if (!asBoolean(statementList)) {
firstLabelHolder.add(tuple.getV1());
}
for (int i = 0, n = tuple.getV2().size(); i < n; i++) {
Expression expr = tuple.getV2().get(i);
statementList.add(configureAST(new CaseStatement(expr, // check whether processing the last label. if yes, block statement should be attached.
(isLast && i == n - 1) ? codeBlock : EmptyStatement.INSTANCE), firstLabelHolder.get(0)));
}
break;
}
case DEFAULT:
{
codeBlock.putNodeMetaData(IS_SWITCH_DEFAULT, true);
statementList.add(// this.configureAST(codeBlock, tuple.getKey())
codeBlock);
break;
}
}
return statementList;
});
return tuple(result, isArrowHolder[0], hasResultStmtHolder[0]);
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.FOR in project groovy by apache.
the class AstBuilder method transformRecordHeaderToProperties.
private void transformRecordHeaderToProperties(ClassDeclarationContext ctx, ClassNode classNode) {
Parameter[] parameters = this.visitFormalParameters(ctx.formalParameters());
classNode.putNodeMetaData(RECORD_HEADER, parameters);
final int n = parameters.length;
for (int i = 0; i < n; i += 1) {
Parameter parameter = parameters[i];
FormalParameterContext parameterCtx = parameter.getNodeMetaData(PARAMETER_CONTEXT);
ModifierManager parameterModifierManager = parameter.getNodeMetaData(PARAMETER_MODIFIER_MANAGER);
ClassNode originType = parameter.getOriginType();
PropertyNode propertyNode = declareProperty(parameterCtx, parameterModifierManager, originType, classNode, i, parameter, parameter.getName(), parameter.getModifiers(), parameter.getInitialExpression());
propertyNode.getField().putNodeMetaData(IS_RECORD_GENERATED, Boolean.TRUE);
}
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.FOR in project groovy by apache.
the class SmartDocumentFilter method findTokensToRender.
private List<Token> findTokensToRender(List<Token> tokenList) {
final Tuple2<Integer, Integer> renderRange = getRenderRange();
if (null != renderRange) {
long startLine = lineNumber(renderRange.getV1());
long stopLine = lineNumber(renderRange.getV2());
// should never happen
if (startLine < 0 || stopLine < 0)
return tokenList;
return tokenList.stream().filter(e -> e.getLine() >= startLine && PositionConfigureUtils.endPosition(e).getV1() <= stopLine).collect(Collectors.toList());
}
List<Token> tmpLatestTokenList = filterNewlines(this.latestTokenList);
int latestTokenListSize = tmpLatestTokenList.size();
if (0 == latestTokenListSize) {
return tokenList;
}
List<Token> tmpTokenList = filterNewlines(tokenList);
int tmpTokenListSize = tmpTokenList.size();
if (0 == tmpTokenListSize) {
return tokenList;
}
int startTokenIndex = 0;
int minSize = Math.min(tmpTokenListSize, latestTokenListSize);
for (int i = 0; i < minSize; i++) {
Token token = tmpTokenList.get(i);
Token latestToken = tmpLatestTokenList.get(i);
if (token.getType() == latestToken.getType() && token.getStartIndex() == latestToken.getStartIndex() && token.getStopIndex() == latestToken.getStopIndex()) {
continue;
}
startTokenIndex = i;
break;
}
List<Token> newTokenList = new ReversedList<>(tmpTokenList);
List<Token> newLatestTokenList = new ReversedList<>(tmpLatestTokenList);
int stopTokenIndex = tmpTokenListSize;
Token lastToken = newTokenList.get(0);
Token lastLatestToken = newLatestTokenList.get(0);
for (int i = 0; i < minSize; i++) {
Token token = newTokenList.get(i);
Token latestToken = newLatestTokenList.get(i);
if ((token.getType() == latestToken.getType()) && (token.getStartIndex() - lastToken.getStartIndex()) == (latestToken.getStartIndex() - lastLatestToken.getStartIndex()) && ((token.getStopIndex() - lastToken.getStopIndex()) == (latestToken.getStopIndex() - lastLatestToken.getStopIndex()))) {
continue;
}
stopTokenIndex = tmpTokenListSize - i;
break;
}
if (startTokenIndex == stopTokenIndex) {
return tmpTokenListSize != latestTokenListSize ? tokenList : Collections.emptyList();
} else if (startTokenIndex < stopTokenIndex) {
return tmpTokenList.subList(startTokenIndex, stopTokenIndex);
}
// should never reach here. If unexpected error occurred, it's better to render all tokens
return tokenList;
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.FOR in project groovy by apache.
the class AstBuilder method visitClassDeclaration.
@Override
public ClassNode visitClassDeclaration(final ClassDeclarationContext ctx) {
String packageName = Optional.ofNullable(moduleNode.getPackageName()).orElse("");
String className = this.visitIdentifier(ctx.identifier());
if (VAR_STR.equals(className)) {
throw createParsingFailedException("var cannot be used for type declarations", ctx.identifier());
}
boolean isAnnotation = asBoolean(ctx.AT());
if (isAnnotation) {
if (asBoolean(ctx.typeParameters())) {
throw createParsingFailedException("annotation declaration cannot have type parameters", ctx.typeParameters());
}
if (asBoolean(ctx.EXTENDS())) {
throw createParsingFailedException("No extends clause allowed for annotation declaration", ctx.EXTENDS());
}
if (asBoolean(ctx.IMPLEMENTS())) {
throw createParsingFailedException("No implements clause allowed for annotation declaration", ctx.IMPLEMENTS());
}
}
boolean isEnum = asBoolean(ctx.ENUM());
if (isEnum) {
if (asBoolean(ctx.typeParameters())) {
throw createParsingFailedException("enum declaration cannot have type parameters", ctx.typeParameters());
}
if (asBoolean(ctx.EXTENDS())) {
throw createParsingFailedException("No extends clause allowed for enum declaration", ctx.EXTENDS());
}
}
boolean isInterface = (asBoolean(ctx.INTERFACE()) && !isAnnotation);
if (isInterface) {
if (asBoolean(ctx.IMPLEMENTS())) {
throw createParsingFailedException("No implements clause allowed for interface declaration", ctx.IMPLEMENTS());
}
}
List<ModifierNode> modifierNodeList = ctx.getNodeMetaData(TYPE_DECLARATION_MODIFIERS);
Objects.requireNonNull(modifierNodeList, "modifierNodeList should not be null");
ModifierManager modifierManager = new ModifierManager(this, modifierNodeList);
Optional<ModifierNode> finalModifierNodeOptional = modifierManager.get(FINAL);
Optional<ModifierNode> sealedModifierNodeOptional = modifierManager.get(SEALED);
Optional<ModifierNode> nonSealedModifierNodeOptional = modifierManager.get(NON_SEALED);
boolean isFinal = finalModifierNodeOptional.isPresent();
boolean isSealed = sealedModifierNodeOptional.isPresent();
boolean isNonSealed = nonSealedModifierNodeOptional.isPresent();
boolean isRecord = asBoolean(ctx.RECORD());
boolean hasRecordHeader = asBoolean(ctx.formalParameters());
if (isRecord) {
if (asBoolean(ctx.EXTENDS())) {
throw createParsingFailedException("No extends clause allowed for record declaration", ctx.EXTENDS());
}
if (!hasRecordHeader) {
throw createParsingFailedException("header declaration of record is expected", ctx.identifier());
}
if (isSealed) {
throw createParsingFailedException("`sealed` is not allowed for record declaration", sealedModifierNodeOptional.get());
}
if (isNonSealed) {
throw createParsingFailedException("`non-sealed` is not allowed for record declaration", nonSealedModifierNodeOptional.get());
}
} else {
if (hasRecordHeader) {
throw createParsingFailedException("header declaration is only allowed for record declaration", ctx.formalParameters());
}
}
if (isSealed && isNonSealed) {
throw createParsingFailedException("type cannot be defined with both `sealed` and `non-sealed`", nonSealedModifierNodeOptional.get());
}
if (isFinal && (isSealed || isNonSealed)) {
throw createParsingFailedException("type cannot be defined with both " + (isSealed ? "`sealed`" : "`non-sealed`") + " and `final`", finalModifierNodeOptional.get());
}
if ((isAnnotation || isEnum) && (isSealed || isNonSealed)) {
ModifierNode mn = isSealed ? sealedModifierNodeOptional.get() : nonSealedModifierNodeOptional.get();
throw createParsingFailedException("modifier `" + mn.getText() + "` is not allowed for " + (isEnum ? "enum" : "annotation definition"), mn);
}
boolean hasPermits = asBoolean(ctx.PERMITS());
if (!isSealed && hasPermits) {
throw createParsingFailedException("only sealed type declarations should have `permits` clause", ctx);
}
int modifiers = modifierManager.getClassModifiersOpValue();
boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
modifiers &= ~Opcodes.ACC_SYNTHETIC;
ClassNode classNode, outerClass = classNodeStack.peek();
if (isEnum) {
classNode = EnumHelper.makeEnumNode(asBoolean(outerClass) ? className : packageName + className, modifiers, null, outerClass);
} else if (asBoolean(outerClass)) {
if (outerClass.isInterface())
modifiers |= Opcodes.ACC_STATIC;
classNode = new InnerClassNode(outerClass, outerClass.getName() + "$" + className, modifiers, ClassHelper.OBJECT_TYPE.getPlainNodeReference());
} else {
classNode = new ClassNode(packageName + className, modifiers, ClassHelper.OBJECT_TYPE.getPlainNodeReference());
}
configureAST(classNode, ctx);
classNode.setSyntheticPublic(syntheticPublic);
classNode.setGenericsTypes(this.visitTypeParameters(ctx.typeParameters()));
boolean isInterfaceWithDefaultMethods = (isInterface && this.containsDefaultMethods(ctx));
if (isSealed) {
AnnotationNode sealedAnnotationNode = new AnnotationNode(ClassHelper.makeCached(Sealed.class));
if (asBoolean(ctx.ps)) {
ListExpression permittedSubclassesListExpression = listX(Arrays.stream(this.visitTypeList(ctx.ps)).map(ClassExpression::new).collect(Collectors.toList()));
sealedAnnotationNode.setMember("permittedSubclasses", permittedSubclassesListExpression);
configureAST(sealedAnnotationNode, ctx.PERMITS());
sealedAnnotationNode.setNodeMetaData("permits", true);
}
classNode.addAnnotation(sealedAnnotationNode);
} else if (isNonSealed) {
classNode.addAnnotation(new AnnotationNode(ClassHelper.makeCached(NonSealed.class)));
}
if (isInterfaceWithDefaultMethods || asBoolean(ctx.TRAIT())) {
classNode.addAnnotation(new AnnotationNode(ClassHelper.makeCached(Trait.class)));
}
if (isRecord) {
classNode.addAnnotation(new AnnotationNode(RECORD_TYPE_CLASS));
}
classNode.addAnnotations(modifierManager.getAnnotations());
if (isInterfaceWithDefaultMethods) {
classNode.putNodeMetaData(IS_INTERFACE_WITH_DEFAULT_METHODS, Boolean.TRUE);
}
classNode.putNodeMetaData(CLASS_NAME, className);
if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT())) {
if (asBoolean(ctx.scs)) {
ClassNode[] scs = this.visitTypeList(ctx.scs);
if (scs.length > 1) {
throw createParsingFailedException("Cannot extend multiple classes", ctx.EXTENDS());
}
classNode.setSuperClass(scs[0]);
}
classNode.setInterfaces(this.visitTypeList(ctx.is));
this.initUsingGenerics(classNode);
} else if (isInterfaceWithDefaultMethods) {
// GROOVY-9259
classNode.setInterfaces(this.visitTypeList(ctx.scs));
this.initUsingGenerics(classNode);
} else if (isInterface) {
classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT);
classNode.setInterfaces(this.visitTypeList(ctx.scs));
this.initUsingGenerics(classNode);
this.hackMixins(classNode);
} else if (isEnum || isRecord) {
classNode.setInterfaces(this.visitTypeList(ctx.is));
this.initUsingGenerics(classNode);
if (isRecord) {
transformRecordHeaderToProperties(ctx, classNode);
}
} else if (isAnnotation) {
classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_ANNOTATION);
classNode.addInterface(ClassHelper.Annotation_TYPE);
this.hackMixins(classNode);
} else {
throw createParsingFailedException("Unsupported class declaration: " + ctx.getText(), ctx);
}
// have here to ensure it won't be the inner class
if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT())) {
classNodeList.add(classNode);
}
classNodeStack.push(classNode);
ctx.classBody().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
this.visitClassBody(ctx.classBody());
if (isRecord) {
Optional<FieldNode> fieldNodeOptional = classNode.getFields().stream().filter(f -> !isTrue(f, IS_RECORD_GENERATED) && !f.isStatic()).findFirst();
if (fieldNodeOptional.isPresent()) {
createParsingFailedException("Instance field is not allowed in `record`", fieldNodeOptional.get());
}
}
classNodeStack.pop();
if (!(asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT()))) {
classNodeList.add(classNode);
}
groovydocManager.handle(classNode, ctx);
return classNode;
}
use of org.apache.groovy.parser.antlr4.GroovyLexer.FOR in project groovy by apache.
the class SmartDocumentFilter method parseDocument.
private void parseDocument() throws BadLocationException {
GroovyLangLexer lexer;
try {
lexer = createLexer(styledDocument.getText(0, styledDocument.getLength()));
} catch (IOException e) {
e.printStackTrace();
this.latest = false;
return;
}
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
try {
tokenStream.fill();
} catch (LexerNoViableAltException | GroovySyntaxError e) {
// ignore
this.latest = false;
return;
} catch (Exception e) {
e.printStackTrace();
this.latest = false;
return;
}
List<Token> tokenList = tokenStream.getTokens();
List<Token> tokenListToRender;
try {
tokenListToRender = findTokensToRender(tokenList);
} finally {
this.setRenderRange(null);
}
for (Token token : tokenListToRender) {
int tokenType = token.getType();
if (EOF == tokenType) {
continue;
}
int tokenStartIndex = token.getStartIndex();
int tokenStopIndex = token.getStopIndex();
int tokenLength = tokenStopIndex - tokenStartIndex + 1;
styledDocument.setCharacterAttributes(tokenStartIndex, tokenLength, findStyleByTokenType(tokenType), true);
if (GStringBegin == tokenType || GStringPart == tokenType) {
styledDocument.setCharacterAttributes(tokenStartIndex + tokenLength - 1, 1, defaultStyle, true);
}
}
this.latestTokenList = tokenList;
this.latest = true;
}
Aggregations