Skip to content

Commit 9a8c8d8

Browse files
committed
GROOVY-9707
1 parent 1b4760f commit 9a8c8d8

7 files changed

Lines changed: 239 additions & 0 deletions

File tree

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,31 @@ public void testTypeChecked9570() {
430430
runNegativeTest(sources, "");
431431
}
432432

433+
@Test
434+
public void testTypeChecked9707() {
435+
Map<String, String> options = getCompilerOptions();
436+
options.put(CompilerOptions.OPTIONG_GroovyCompilerConfigScript, createScript("config.groovy",
437+
"withConfig(configuration) {\n" +
438+
" ast(groovy.transform.CompileStatic)\n" +
439+
"}\n"
440+
).getAbsolutePath());
441+
442+
//@formatter:off
443+
String[] sources = {
444+
"Main.groovy",
445+
"@groovy.transform.TypeChecked\n" +
446+
"class C {\n" +
447+
" def m() {\n" +
448+
" 'a' + 'b'\n" +
449+
" }\n" +
450+
"}\n" +
451+
"print new C().m()\n",
452+
};
453+
//@formatter:on
454+
455+
runConformTest(sources, "ab", options);
456+
}
457+
433458
@Test
434459
public void testTypeChecked9735() {
435460
//@formatter:off

base/org.codehaus.groovy30/.checkstyle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
<file-match-pattern match-pattern="groovy/transform/FieldASTTransformation.java" include-pattern="false" />
7070
<file-match-pattern match-pattern="groovy/transform/LogASTTransformation.java" include-pattern="false" />
7171
<file-match-pattern match-pattern="groovy/transform/sc/StaticCompilationVisitor.java" include-pattern="false" />
72+
<file-match-pattern match-pattern="groovy/transform/sc/StaticCompileTransformation.java" include-pattern="false" />
7273
<file-match-pattern match-pattern="groovy/transform/sc/transformers/(Binary|MethodCall)ExpressionTransformer.java" include-pattern="false" />
7374
<file-match-pattern match-pattern="groovy/transform/sc/transformers/CompareToNullExpression.java" include-pattern="false" />
7475
<file-match-pattern match-pattern="groovy/transform/stc/AbstractExtensionMethodCache.java" include-pattern="false" />
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.codehaus.groovy.transform.sc;
20+
21+
import org.codehaus.groovy.ast.ASTNode;
22+
import org.codehaus.groovy.ast.AnnotatedNode;
23+
import org.codehaus.groovy.ast.AnnotationNode;
24+
import org.codehaus.groovy.ast.ClassNode;
25+
import org.codehaus.groovy.ast.MethodNode;
26+
import org.codehaus.groovy.ast.expr.Expression;
27+
import org.codehaus.groovy.classgen.asm.WriterControllerFactory;
28+
import org.codehaus.groovy.classgen.asm.sc.StaticTypesWriterControllerFactoryImpl;
29+
import org.codehaus.groovy.control.CompilePhase;
30+
import org.codehaus.groovy.control.SourceUnit;
31+
import org.codehaus.groovy.syntax.SyntaxException;
32+
import org.codehaus.groovy.transform.GroovyASTTransformation;
33+
import org.codehaus.groovy.transform.StaticTypesTransformation;
34+
import org.codehaus.groovy.transform.sc.transformers.StaticCompilationTransformer;
35+
import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
36+
37+
import java.util.Collections;
38+
import java.util.Map;
39+
40+
import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.STATIC_COMPILE_NODE;
41+
42+
/**
43+
* Handles the implementation of the {@link groovy.transform.CompileStatic} transformation.
44+
*/
45+
@GroovyASTTransformation(phase = CompilePhase.INSTRUCTION_SELECTION)
46+
public class StaticCompileTransformation extends StaticTypesTransformation {
47+
48+
private final StaticTypesWriterControllerFactoryImpl factory = new StaticTypesWriterControllerFactoryImpl();
49+
50+
@Override
51+
public void visit(final ASTNode[] nodes, final SourceUnit source) {
52+
AnnotationNode annotationInformation = (AnnotationNode) nodes[0];
53+
AnnotatedNode node = (AnnotatedNode) nodes[1];
54+
// GRECLIPSE add -- GROOVY-9707
55+
if (node.getNodeMetaData(StaticTypeCheckingVisitor.class)!=null){
56+
return;
57+
}
58+
// GRECLIPSE end
59+
StaticTypeCheckingVisitor visitor = null;
60+
Map<String,Expression> members = annotationInformation.getMembers();
61+
Expression extensions = members.get("extensions");
62+
if (node instanceof ClassNode) {
63+
ClassNode classNode = (ClassNode) node;
64+
visitor = newVisitor(source, classNode);
65+
visitor.setCompilationUnit(compilationUnit);
66+
addTypeCheckingExtensions(visitor, extensions);
67+
classNode.putNodeMetaData(WriterControllerFactory.class, factory);
68+
node.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
69+
visitor.initialize();
70+
visitor.visitClass(classNode);
71+
} else if (node instanceof MethodNode) {
72+
MethodNode methodNode = (MethodNode) node;
73+
ClassNode declaringClass = methodNode.getDeclaringClass();
74+
visitor = newVisitor(source, declaringClass);
75+
visitor.setCompilationUnit(compilationUnit);
76+
addTypeCheckingExtensions(visitor, extensions);
77+
methodNode.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
78+
if (declaringClass.getNodeMetaData(WriterControllerFactory.class) == null) {
79+
declaringClass.putNodeMetaData(WriterControllerFactory.class, factory);
80+
}
81+
visitor.setMethodsToBeVisited(Collections.singleton(methodNode));
82+
visitor.initialize();
83+
visitor.visitMethod(methodNode);
84+
} else {
85+
source.addError(new SyntaxException(STATIC_ERROR_PREFIX + "Unimplemented node type",
86+
node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()));
87+
}
88+
if (visitor != null) {
89+
visitor.performSecondPass();
90+
}
91+
StaticCompilationTransformer transformer = new StaticCompilationTransformer(source, visitor);
92+
if (node instanceof ClassNode) {
93+
transformer.visitClass((ClassNode) node);
94+
} else if (node instanceof MethodNode) {
95+
transformer.visitMethod((MethodNode) node);
96+
}
97+
}
98+
99+
@Override
100+
protected StaticTypeCheckingVisitor newVisitor(final SourceUnit unit, final ClassNode node) {
101+
return new StaticCompilationVisitor(unit, node);
102+
}
103+
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@ public void visitClass(final ClassNode node) {
414414
}
415415

416416
node.putNodeMetaData(INFERRED_TYPE, node);
417+
// GRECLIPSE add -- GROOVY-9707
418+
node.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
419+
// GRECLIPSE end
417420
// mark all methods as visited. We can't do this in visitMethod because the type checker
418421
// works in a two pass sequence and we don't want to skip the second pass
419422
node.getMethods().forEach(n -> n.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE));

base/org.codehaus.groovy40/.checkstyle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<file-match-pattern match-pattern="groovy/transform/LogASTTransformation.java" include-pattern="false" />
6767
<file-match-pattern match-pattern="groovy/transform/NotYetImplemented.java" include-pattern="false" />
6868
<file-match-pattern match-pattern="groovy/transform/sc/StaticCompilationVisitor.java" include-pattern="false" />
69+
<file-match-pattern match-pattern="groovy/transform/sc/StaticCompileTransformation.java" include-pattern="false" />
6970
<file-match-pattern match-pattern="groovy/transform/sc/transformers/(Binary|MethodCall)ExpressionTransformer.java" include-pattern="false" />
7071
<file-match-pattern match-pattern="groovy/transform/sc/transformers/CompareToNullExpression.java" include-pattern="false" />
7172
<file-match-pattern match-pattern="groovy/transform/stc/StaticTypeCheckingSupport.java" include-pattern="false" />
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.codehaus.groovy.transform.sc;
20+
21+
import org.codehaus.groovy.ast.ASTNode;
22+
import org.codehaus.groovy.ast.AnnotatedNode;
23+
import org.codehaus.groovy.ast.AnnotationNode;
24+
import org.codehaus.groovy.ast.ClassNode;
25+
import org.codehaus.groovy.ast.MethodNode;
26+
import org.codehaus.groovy.ast.expr.Expression;
27+
import org.codehaus.groovy.classgen.asm.WriterControllerFactory;
28+
import org.codehaus.groovy.classgen.asm.sc.StaticTypesWriterControllerFactoryImpl;
29+
import org.codehaus.groovy.control.CompilePhase;
30+
import org.codehaus.groovy.control.SourceUnit;
31+
import org.codehaus.groovy.syntax.SyntaxException;
32+
import org.codehaus.groovy.transform.GroovyASTTransformation;
33+
import org.codehaus.groovy.transform.StaticTypesTransformation;
34+
import org.codehaus.groovy.transform.sc.transformers.StaticCompilationTransformer;
35+
import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
36+
37+
import java.util.Collections;
38+
import java.util.Map;
39+
40+
import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.STATIC_COMPILE_NODE;
41+
42+
/**
43+
* Handles the implementation of the {@link groovy.transform.CompileStatic} transformation.
44+
*/
45+
@GroovyASTTransformation(phase = CompilePhase.INSTRUCTION_SELECTION)
46+
public class StaticCompileTransformation extends StaticTypesTransformation {
47+
48+
private final StaticTypesWriterControllerFactoryImpl factory = new StaticTypesWriterControllerFactoryImpl();
49+
50+
@Override
51+
public void visit(final ASTNode[] nodes, final SourceUnit source) {
52+
AnnotationNode annotationInformation = (AnnotationNode) nodes[0];
53+
AnnotatedNode node = (AnnotatedNode) nodes[1];
54+
// GRECLIPSE add -- GROOVY-9707
55+
if (node.getNodeMetaData(StaticTypeCheckingVisitor.class)!=null){
56+
return;
57+
}
58+
// GRECLIPSE end
59+
StaticTypeCheckingVisitor visitor = null;
60+
Map<String,Expression> members = annotationInformation.getMembers();
61+
Expression extensions = members.get("extensions");
62+
if (node instanceof ClassNode) {
63+
ClassNode classNode = (ClassNode) node;
64+
visitor = newVisitor(source, classNode);
65+
visitor.setCompilationUnit(compilationUnit);
66+
addTypeCheckingExtensions(visitor, extensions);
67+
classNode.putNodeMetaData(WriterControllerFactory.class, factory);
68+
node.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
69+
visitor.initialize();
70+
visitor.visitClass(classNode);
71+
} else if (node instanceof MethodNode) {
72+
MethodNode methodNode = (MethodNode) node;
73+
ClassNode declaringClass = methodNode.getDeclaringClass();
74+
visitor = newVisitor(source, declaringClass);
75+
visitor.setCompilationUnit(compilationUnit);
76+
addTypeCheckingExtensions(visitor, extensions);
77+
methodNode.putNodeMetaData(STATIC_COMPILE_NODE, !visitor.isSkipMode(node));
78+
if (declaringClass.getNodeMetaData(WriterControllerFactory.class) == null) {
79+
declaringClass.putNodeMetaData(WriterControllerFactory.class, factory);
80+
}
81+
visitor.setMethodsToBeVisited(Collections.singleton(methodNode));
82+
visitor.initialize();
83+
visitor.visitMethod(methodNode);
84+
} else {
85+
source.addError(new SyntaxException(STATIC_ERROR_PREFIX + "Unimplemented node type",
86+
node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()));
87+
}
88+
if (visitor != null) {
89+
visitor.performSecondPass();
90+
}
91+
StaticCompilationTransformer transformer = new StaticCompilationTransformer(source, visitor);
92+
if (node instanceof ClassNode) {
93+
transformer.visitClass((ClassNode) node);
94+
} else if (node instanceof MethodNode) {
95+
transformer.visitMethod((MethodNode) node);
96+
}
97+
}
98+
99+
@Override
100+
protected StaticTypeCheckingVisitor newVisitor(final SourceUnit unit, final ClassNode node) {
101+
return new StaticCompilationVisitor(unit, node);
102+
}
103+
}

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@ public void visitClass(final ClassNode node) {
414414
}
415415

416416
node.putNodeMetaData(INFERRED_TYPE, node);
417+
// GRECLIPSE add -- GROOVY-9707
418+
node.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
419+
// GRECLIPSE end
417420
// mark all methods as visited. We can't do this in visitMethod because the type checker
418421
// works in a two pass sequence and we don't want to skip the second pass
419422
node.getMethods().forEach(n -> n.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE));

0 commit comments

Comments
 (0)