You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/04/11 01:37:42 UTC
[06/50] groovy git commit: Breaking change: allow lower case type
names except return type name of method declaration
Breaking change: allow lower case type names except return type name of method declaration
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/d3c68531
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/d3c68531
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/d3c68531
Branch: refs/heads/master
Commit: d3c68531e36908680b7ac60b9cbf1a01601e10ae
Parents: c9fbf95
Author: sunlan <su...@apache.org>
Authored: Sat Jan 21 11:57:07 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Sat Jan 21 11:57:07 2017 +0800
----------------------------------------------------------------------
.../apache/groovy/parser/antlr4/GroovyParser.g4 | 37 +++++++++-----
.../apache/groovy/parser/antlr4/AstBuilder.java | 30 +++++------
.../parser/antlr4/SemanticPredicates.java | 52 ++++++++++++++++++--
.../parser/antlr4/GroovyParserTest.groovy | 6 +++
.../resources/core/BreakingChange_01x.groovy | 24 +++++++++
.../resources/core/BreakingChange_02x.groovy | 9 ++++
.../resources/core/BreakingChange_03x.groovy | 16 ++++++
.../resources/core/BreakingChange_04x.groovy | 26 ++++++++++
.../resources/core/ClassDeclaration_01.groovy | 10 +++-
.../src/test/resources/core/Command_01.groovy | 6 ++-
10 files changed, 184 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4 b/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
index 5cefb90..6f94ec6 100644
--- a/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
+++ b/subprojects/groovy-parser-antlr4/src/main/antlr4/org/apache/groovy/parser/antlr4/GroovyParser.g4
@@ -310,11 +310,10 @@ methodDeclaration[int t, int ct]
: { 3 == $ct }?
returnType[$ct] methodName LPAREN rparen (DEFAULT nls elementValue)?
|
- ( modifiersOpt typeParameters? returnType[$ct]
- | modifiers typeParameters? returnType[$ct]?
- |
- { 0 == $t }?
+ ( { 0 == $t }?
modifiersOpt typeParameters?
+ | modifiersOpt typeParameters? returnType[$ct]
+ | modifiers typeParameters? returnType[$ct]?
)
methodName formalParameters (nls THROWS nls qualifiedClassNameList)?
(
@@ -333,7 +332,7 @@ methodName
returnType[int ct]
:
- type
+ standardType
|
// annotation method can not have void return type
{ 3 != $ct }? VOID
@@ -365,12 +364,25 @@ arrayInitializer
: LBRACK (variableInitializer (COMMA variableInitializer)* (COMMA)? )? RBRACK
;
+standardType
+options { baseContext = type; }
+ : primitiveType (LBRACK RBRACK)*
+ | standardClassOrInterfaceType (LBRACK RBRACK)*
+ ;
+
type
: primitiveType (LBRACK RBRACK)*
| classOrInterfaceType (LBRACK RBRACK)*
;
classOrInterfaceType
+ : ( qualifiedClassName
+ | qualifiedStandardClassName
+ ) typeArguments?
+ ;
+
+standardClassOrInterfaceType
+options { baseContext = classOrInterfaceType; }
: qualifiedStandardClassName typeArguments?
;
@@ -559,23 +571,24 @@ blockStatement
;
localVariableDeclaration
- : variableDeclaration[0]
+ : { !SemanticPredicates.isInvalidLocalVariableDeclaration(_input) }?
+ variableDeclaration[0]
;
/**
* t 0: local variable declaration; 1: field declaration
*/
variableDeclaration[int t]
- : ( { 0 == $t }? variableModifiersOpt
- | { 1 == $t }? modifiersOpt
- )
- type variableDeclarators
- |
- ( { 0 == $t }? variableModifiers
+ : ( { 0 == $t }? variableModifiers
| { 1 == $t }? modifiers
)
type? variableDeclarators
|
+ ( { 0 == $t }? variableModifiersOpt
+ | { 1 == $t }? modifiersOpt
+ )
+ type variableDeclarators
+ |
( { 0 == $t }? variableModifiers
| { 1 == $t }? modifiers
)
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index c61a2c0..8ab5578 100644
--- a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -3239,8 +3239,14 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
@Override
public ClassNode visitClassOrInterfaceType(ClassOrInterfaceTypeContext ctx) {
- ctx.qualifiedStandardClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
- ClassNode classNode = this.visitQualifiedStandardClassName(ctx.qualifiedStandardClassName());
+ ClassNode classNode;
+ if (asBoolean(ctx.qualifiedClassName())) {
+ ctx.qualifiedClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
+ classNode = this.visitQualifiedClassName(ctx.qualifiedClassName());
+ } else {
+ ctx.qualifiedStandardClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
+ classNode = this.visitQualifiedStandardClassName(ctx.qualifiedStandardClassName());
+ }
if (asBoolean(ctx.typeArguments())) {
classNode.setGenericsTypes(
@@ -3496,19 +3502,15 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
@Override
public ClassNode visitQualifiedClassName(QualifiedClassNameContext ctx) {
- ClassNode result = ClassHelper.make(ctx.getText());
-
- /*
- if (!isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR)) { // type in the "instanceof" expression should not have proxy to redirect to it
- result = this.proxyClassNode(result);
- }
- */
-
- return this.configureAST(result, ctx);
+ return this.createClassNode(ctx);
}
@Override
public ClassNode visitQualifiedStandardClassName(QualifiedStandardClassNameContext ctx) {
+ return this.createClassNode(ctx);
+ }
+
+ private ClassNode createClassNode(GroovyParserRuleContext ctx) {
ClassNode result = ClassHelper.make(ctx.getText());
if (!isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR)) { // type in the "instanceof" expression should not have proxy to redirect to it
@@ -4257,7 +4259,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
* <p>
* Created by Daniel.Sun on 2016/08/23.
*/
- private static class ModifierNode extends ASTNode {
+ public static class ModifierNode extends ASTNode {
private Integer type;
private Integer opCode; // ASM opcode
private String text;
@@ -4265,7 +4267,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
private boolean repeatable;
public static final int ANNOTATION_TYPE = -999;
- private static final Map<Integer, Integer> MAP = new HashMap<Integer, Integer>() {
+ public static final Map<Integer, Integer> MODIFIER_OPCODE_MAP = new HashMap<Integer, Integer>() {
{
put(ANNOTATION_TYPE, 0);
put(DEF, 0);
@@ -4288,7 +4290,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
public ModifierNode(Integer type) {
this.type = type;
- this.opCode = MAP.get(type);
+ this.opCode = MODIFIER_OPCODE_MAP.get(type);
this.repeatable = ANNOTATION_TYPE == type; // Only annotations are repeatable
if (!asBoolean((Object) this.opCode)) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
index e306e89..811276f 100644
--- a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
+++ b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/SemanticPredicates.java
@@ -19,11 +19,13 @@
package org.apache.groovy.parser.antlr4;
import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
-import static org.apache.groovy.parser.antlr4.GroovyParser.CapitalizedIdentifier;
-import static org.apache.groovy.parser.antlr4.GroovyParser.Identifier;
-import static org.apache.groovy.parser.antlr4.GroovyParser.StringLiteral;
+import java.util.Collections;
+import java.util.Set;
+
+import static org.apache.groovy.parser.antlr4.GroovyParser.*;
/**
* Some semantic predicates for altering the behaviour of the lexer and parser
@@ -103,6 +105,48 @@ public class SemanticPredicates {
int tokenType = ts.LT(1).getType();
return (Identifier == tokenType || CapitalizedIdentifier == tokenType || StringLiteral == tokenType)
- && GroovyLangParser.LPAREN == (ts.LT(2).getType());
+ && LPAREN == (ts.LT(2).getType());
}
+
+ private static final Set<Integer> MODIFIER_SET =
+ Collections.unmodifiableSet(AstBuilder.ModifierNode.MODIFIER_OPCODE_MAP.keySet());
+ /**
+ * Distinguish between local variable declaration and method call, e.g. `a b`
+ */
+ public static boolean isInvalidLocalVariableDeclaration(TokenStream ts) {
+ int index = 2;
+ Token token;
+ int tokenType;
+ int tokenType2 = ts.LT(index).getType();
+ int tokenType3;
+
+ if (DOT == tokenType2) {
+ int tokeTypeN = tokenType2;
+
+ do {
+ index = index + 2;
+ tokeTypeN = ts.LT(index).getType();
+ } while (DOT == tokeTypeN);
+
+ if (LT == tokeTypeN || LBRACK == tokeTypeN) {
+ return false;
+ }
+
+ index = index - 1;
+ tokenType2 = ts.LT(index + 1).getType();
+ } else {
+ index = 1;
+ }
+
+ token = ts.LT(index);
+ tokenType = token.getType();
+ tokenType3 = ts.LT(index + 2).getType();
+
+ return VOID == tokenType
+ || !(BuiltInPrimitiveType == tokenType || MODIFIER_SET.contains(tokenType))
+ && Character.isLowerCase(token.getText().codePointAt(0))
+ && !(ASSIGN == tokenType3 || (LT == tokenType2 || LBRACK == tokenType2));
+
+ }
+
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy b/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
index 003a34b..98d434c 100644
--- a/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
+++ b/subprojects/groovy-parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
@@ -333,4 +333,10 @@ class GroovyParserTest extends GroovyTestCase {
doRunAndTest('bugs/BUG-GROOVY-4762.groovy');
}
+ void "test groovy core - BreakingChanges"() {
+ doRunAndTest('core/BreakingChange_01x.groovy');
+ doRunAndTest('core/BreakingChange_02x.groovy');
+ doRunAndTest('core/BreakingChange_03x.groovy');
+ doRunAndTest('core/BreakingChange_04x.groovy');
+ }
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy
new file mode 100644
index 0000000..3f3b856
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_01x.groovy
@@ -0,0 +1,24 @@
+package core
+
+class a<T> {
+ int x = 1;
+}
+
+a b = new a()
+assert b.x == 1
+
+a<String> b2 = new a<String>()
+assert b2.x == 1
+
+a<String>[] b3 = new a<String>[0]
+assert b3.length == 0
+
+core.a b4 = new a()
+assert b4.x == 1
+
+core.a<String> b5 = new a<String>()
+assert b5.x == 1
+
+core.a<String>[] b6 = new a<String>[0]
+assert b6.length == 0
+
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy
new file mode 100644
index 0000000..62e90ed
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_02x.groovy
@@ -0,0 +1,9 @@
+package core
+
+import java.util.concurrent.atomic.AtomicInteger
+
+def inc(AtomicInteger x) { x.incrementAndGet() }
+def a = new AtomicInteger(0)
+
+inc a
+assert 1 == a.get()
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy
new file mode 100644
index 0000000..b78abf5
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_03x.groovy
@@ -0,0 +1,16 @@
+package core
+
+class a {}
+a[] b
+b = new a[0]
+assert 0 == b.length
+
+a[] b2 = new a[0]
+assert 0 == b2.length
+
+core.a[] b3
+b3 = new a[0]
+assert 0 == b3.length
+
+core.a[] b4 = new a[0]
+assert 0 == b4.length
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy
new file mode 100644
index 0000000..10cfcac
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/BreakingChange_04x.groovy
@@ -0,0 +1,26 @@
+package core
+
+class B<T> {}
+B b
+b = new B()
+assert b instanceof B
+
+B<String> b2
+b2 = new B<String>()
+assert b2 instanceof B
+
+B<String>[] b3
+b3 = new B<String>[0]
+assert b3 instanceof B[]
+
+core.B b4
+b4 = new B()
+assert b4 instanceof B
+
+core.B<String> b5
+b5 = new B<String>()
+assert b5 instanceof B
+
+core.B<String>[] b6
+b6 = new B<String>[0]
+assert b6 instanceof B[]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
index 13d0b8e..8260899 100644
--- a/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
@@ -44,4 +44,12 @@ C
}
-class a {}
\ No newline at end of file
+class a {}
+
+class OutputTransforms {
+ final static localTransforms = loadOutputTransforms()
+}
+
+class OutputTransforms2 {
+ @Lazy static localTransforms = loadOutputTransforms()
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/groovy/blob/d3c68531/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy b/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
index a6188c4..78b7682 100644
--- a/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
+++ b/subprojects/groovy-parser-antlr4/src/test/resources/core/Command_01.groovy
@@ -11,4 +11,8 @@ z.a x: b(1, 3), y: c(2, 4)
a b(1, 3), c(2, 4)
obj.<Integer, Double>a b(1, 3), c(2, 4), d(3, 5)
println a
-println a = 1
\ No newline at end of file
+// println a = 1 // breaking change
+println a == 1
+
+result.addAll allElements()
+task someTask() {}
\ No newline at end of file