This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY-11642 in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 468f1ea2db15b9a7d85eb92fcabd65d9cf8cd1ef Author: Eric Milles <[email protected]> AuthorDate: Sat May 3 10:22:24 2025 -0500 GROOVY-11642: include annotations and modifiers in inner class offset --- .../apache/groovy/parser/antlr4/AstBuilder.java | 2 +- src/test-resources/bugs/BUG-GROOVY-8426.groovy | 49 ------ .../groovy/parser/antlr4/GroovyParserTest.groovy | 2 - .../codehaus/groovy/antlr/AstBuilderTest.groovy | 175 +++++++++++++++++---- 4 files changed, 144 insertions(+), 84 deletions(-) diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java index 8012ee3a2d..74d8c062e3 100644 --- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java +++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java @@ -1581,7 +1581,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> { } else if (asBoolean(ctx.classDeclaration())) { ctx.classDeclaration().putNodeMetaData(TYPE_DECLARATION_MODIFIERS, this.visitModifiersOpt(ctx.modifiersOpt())); ctx.classDeclaration().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode); - this.visitClassDeclaration(ctx.classDeclaration()); + configureAST(this.visitClassDeclaration(ctx.classDeclaration()), ctx); } return null; diff --git a/src/test-resources/bugs/BUG-GROOVY-8426.groovy b/src/test-resources/bugs/BUG-GROOVY-8426.groovy deleted file mode 100644 index 79a3691174..0000000000 --- a/src/test-resources/bugs/BUG-GROOVY-8426.groovy +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - - -import groovy.transform.CompileDynamic -import org.codehaus.groovy.ast.ClassNode -import org.codehaus.groovy.ast.MethodNode -import org.codehaus.groovy.ast.builder.AstBuilder -import org.codehaus.groovy.ast.stmt.BlockStatement -import static org.codehaus.groovy.control.CompilePhase.CONVERSION - -@CompileDynamic -class Groovy8426Test { - void testMethodBlockStatement() { - def result = new AstBuilder().buildFromString CONVERSION, false, ''' - def method() { - 'return value' - - } - ''' - - ClassNode classNode = result[1] - MethodNode method = classNode.getMethods('method')[0] - BlockStatement statement = method.code - - assert statement.lineNumber == 2 - assert statement.lastLineNumber == 5 - assert statement.columnNumber == 26 - assert statement.lastColumnNumber == 14 - } -} - -new Groovy8426Test().testMethodBlockStatement() diff --git a/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy b/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy index cb39a2e1c3..60973387db 100644 --- a/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy +++ b/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy @@ -32,7 +32,6 @@ import org.codehaus.groovy.syntax.Token import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test -import static org.apache.groovy.parser.antlr4.TestUtils.doRunAndTest import static org.apache.groovy.parser.antlr4.TestUtils.doRunAndTestAntlr4 import static org.apache.groovy.parser.antlr4.TestUtils.doTest @@ -537,7 +536,6 @@ final class GroovyParserTest { doTest('bugs/BUG-GROOVY-8161.groovy') doRunAndTestAntlr4('bugs/GROOVY-8228.groovy') doRunAndTestAntlr4('bugs/BUG-GROOVY-8311.groovy') - doRunAndTest('bugs/BUG-GROOVY-8426.groovy') doTest('bugs/BUG-GROOVY-8511.groovy') doRunAndTestAntlr4('bugs/BUG-GROOVY-8613.groovy') doTest('bugs/BUG-GROOVY-8641.groovy') diff --git a/src/test/groovy/org/codehaus/groovy/antlr/AstBuilderTest.groovy b/src/test/groovy/org/codehaus/groovy/antlr/AstBuilderTest.groovy index dfdeb7fee4..6aaa9de23c 100644 --- a/src/test/groovy/org/codehaus/groovy/antlr/AstBuilderTest.groovy +++ b/src/test/groovy/org/codehaus/groovy/antlr/AstBuilderTest.groovy @@ -18,74 +18,185 @@ */ package org.codehaus.groovy.antlr -import groovy.test.GroovyTestCase +import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.ClassNode -import org.codehaus.groovy.ast.InnerClassNode -import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.builder.AstBuilder import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.ExpressionStatement import org.codehaus.groovy.ast.stmt.Statement +import org.codehaus.groovy.control.CompilePhase +import org.junit.jupiter.api.Test -import static org.codehaus.groovy.control.CompilePhase.CONVERSION +final class AstBuilderTest { -/** - * Test for AstBuilder. - */ -class AstBuilderTest extends GroovyTestCase { + private static ASTNode buildAST(boolean statementsOnly = false, String source) { + List<ASTNode> nodes = new AstBuilder().buildFromString(CompilePhase.CONVERSION, statementsOnly, source) + if (statementsOnly) { + assert nodes.size() == 1 + return nodes[0] // stmts + } + nodes[1] // type + } + @Test void testStatementsOnly() { - def nodes = new AstBuilder().buildFromString CONVERSION, ''' + def node = buildAST true, ''' println 'hello world' ''' - assert nodes.size() == 1 - assert nodes[0] instanceof BlockStatement - assert nodes[0].statements[0] instanceof ExpressionStatement + assert node instanceof BlockStatement stmt + && stmt.statements[0] instanceof ExpressionStatement } - void testInnerClassLineNumbers() { - def nodes = new AstBuilder().buildFromString CONVERSION, ''' + @Test + void testAnonymousInnerClass() { + ClassNode node = buildAST '''\ new Object() { } ''' - assert nodes[1].getClass() == InnerClassNode - assert nodes[1].lineNumber == 2 - assert nodes[1].lastLineNumber == 4 - assert nodes[1].columnNumber == 26 - assert nodes[1].lastColumnNumber == 14 + node = node.innerClasses.next() + + assert node.lineNumber == 1 + assert node.columnNumber == 26 // TODO: 13 + assert node.lastLineNumber == 3 + assert node.lastColumnNumber == 14 + } + + // GROOVY-11642 + @Test + void testInnerClass1() { + ClassNode outer = buildAST '''\ + class Outer { + protected class Inner { + } + } + ''' + + def inner = outer.innerClasses.next() + + assert inner.lineNumber == 2 + assert inner.columnNumber == 17 + assert inner.lastLineNumber == 3 + assert inner.lastColumnNumber == 18 + } + + // GROOVY-11642 + @Test + void testInnerClass2() { + ClassNode outer = buildAST '''\ + class Outer { + @Deprecated class Inner { + } + } + ''' + + def inner = outer.innerClasses.next() + + assert inner.lineNumber == 2 + assert inner.columnNumber == 17 + assert inner.lastLineNumber == 3 + assert inner.lastColumnNumber == 18 + } + + @Test + void testClass() { + ClassNode node = buildAST '''\ + public class C { + } + ''' + + assert node.lineNumber == 1 + assert node.columnNumber == 13 + assert node.lastLineNumber == 2 + assert node.lastColumnNumber == 14 + } + + @Test + void testEnum() { + ClassNode node = buildAST '''\ + public enum E { + } + ''' + + assert node.lineNumber == 1 + assert node.columnNumber == 13 + assert node.lastLineNumber == 2 + assert node.lastColumnNumber == 14 } - void testEnumLineNumbers() { - def result = new AstBuilder().buildFromString CONVERSION, ''' - enum Color { + @Test + void testField() { + ClassNode node = buildAST '''\ + class C { + @Deprecated + protected + int f = + 123 + } + ''' + def field = node.getField('f') + + assert field.lineNumber == 2 + assert field.columnNumber == 17 + assert field.lastLineNumber == 5 + assert field.lastColumnNumber == 20 + } + + @Test + void testMethod() { + ClassNode node = buildAST '''\ + class C { + @Deprecated + protected + void + m(){ + } } ''' - assert result[1].getClass() == ClassNode - assert result[1].lineNumber == 2 - assert result[1].lastLineNumber == 4 - assert result[1].columnNumber == 13 - assert result[1].lastColumnNumber == 14 + def method = node.getMethod('m') + + assert method.lineNumber == 2 + assert method.columnNumber == 17 + assert method.lastLineNumber == 6 + assert method.lastColumnNumber == 18 } + // GROOVY-8426 + @Test + void testMethodBlock() { + ClassNode node = buildAST ''' + def method() { + 'return value' + + } + ''' + + Statement statement = node.getMethod('method').code + + assert statement.lineNumber == 2 + assert statement.columnNumber == 26 + assert statement.lastLineNumber == 5 + assert statement.lastColumnNumber == 14 + } + + @Test void testStatementAfterLabel() { - def nodes = new AstBuilder().buildFromString CONVERSION, false, ''' + ClassNode node = buildAST ''' def method() { label: assert i == 9 } ''' - assert nodes[1].getClass() == ClassNode - MethodNode method = nodes[1].getMethods('method')[0] - Statement statement = method.code.statements[0] + Statement statement = node.getMethod('method').code.statements[0] + assert statement.lineNumber == 4 - assert statement.lastLineNumber == 4 assert statement.columnNumber == 21 + assert statement.lastLineNumber == 4 assert statement.lastColumnNumber == 34 assert statement.statementLabels[0] == 'label' }
