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 2019/09/26 08:45:27 UTC

[groovy] 01/05: Minor refactoring: implement `makeType` for antlr4 parser plugin

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit e59b5529e34291443f4965dcd78b6eb0a9f37e1b
Author: Daniel.Sun <re...@hotmail.com>
AuthorDate: Wed Sep 25 14:36:08 2019 +0800

    Minor refactoring: implement `makeType` for antlr4 parser plugin
    
    As antlr2 parser will be removed in the future, we should not rely on its API
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   | 33 ++++-------
 .../MarkupTemplateTypeCheckingExtension.groovy     | 41 +++++--------
 .../groovy/parser/antlr4/Antlr4ParserPlugin.java   | 68 ++++++++++++++++++++++
 3 files changed, 91 insertions(+), 51 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 082d4b1..69beb13 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -18,14 +18,11 @@
  */
 package org.codehaus.groovy.ast.tools;
 
-import antlr.RecognitionException;
-import antlr.TokenStreamException;
 import groovy.lang.Tuple2;
 import groovy.transform.stc.IncorrectTypeHintException;
+import org.apache.groovy.parser.antlr4.Antlr4ParserPlugin;
+import org.apache.groovy.parser.antlr4.Antlr4PluginFactory;
 import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.antlr.AntlrParserPlugin;
-import org.codehaus.groovy.antlr.parser.GroovyLexer;
-import org.codehaus.groovy.antlr.parser.GroovyRecognizer;
 import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
@@ -34,15 +31,14 @@ import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.stmt.EmptyStatement;
+import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.control.CompilationUnit;
+import org.codehaus.groovy.control.ParserPluginFactory;
 import org.codehaus.groovy.control.ResolveVisitor;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.runtime.memoize.ConcurrentSoftCache;
 import org.codehaus.groovy.runtime.memoize.EvictableCache;
-import org.codehaus.groovy.syntax.ParserException;
-import org.codehaus.groovy.syntax.Reduction;
 
-import java.io.StringReader;
 import java.lang.ref.SoftReference;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -53,7 +49,6 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Predicate;
 
 import static groovy.lang.Tuple.tuple;
@@ -587,20 +582,12 @@ public class GenericsUtils {
             final CompilationUnit compilationUnit,
             final MethodNode mn,
             final ASTNode usage) {
-        GroovyLexer lexer = new GroovyLexer(new StringReader("DummyNode<" + option + ">"));
-        final GroovyRecognizer rn = GroovyRecognizer.make(lexer);
+
         try {
-            rn.classOrInterfaceType(true);
-            final AtomicReference<ClassNode> ref = new AtomicReference<ClassNode>();
-            AntlrParserPlugin plugin = new AntlrParserPlugin() {
-                @Override
-                public ModuleNode buildAST(final SourceUnit sourceUnit, final ClassLoader classLoader, final Reduction cst) throws ParserException {
-                    ref.set(makeTypeWithArguments(rn.getAST()));
-                    return null;
-                }
-            };
-            plugin.buildAST(null, null, null);
-            ClassNode parsedNode = ref.get();
+            Antlr4PluginFactory antlr4PluginFactory = (Antlr4PluginFactory) ParserPluginFactory.antlr4(compilationUnit.getConfiguration());
+            Antlr4ParserPlugin antlr4ParserPlugin = (Antlr4ParserPlugin) antlr4PluginFactory.createParserPlugin();
+            ClassNode parsedNode = antlr4ParserPlugin.makeType("DummyNode<" + option + ">");
+
             // the returned node is DummyNode<Param1, Param2, Param3, ...)
             GenericsType[] parsedNodeGenericsTypes = parsedNode.getGenericsTypes();
             if (parsedNodeGenericsTypes == null) {
@@ -612,7 +599,7 @@ public class GenericsUtils {
                 signature[i] = resolveClassNode(sourceUnit, compilationUnit, mn, usage, genericsType.getType());
             }
             return signature;
-        } catch (RecognitionException | ParserException | TokenStreamException e) {
+        } catch (CompilationFailedException e) {
             sourceUnit.addError(new IncorrectTypeHintException(mn, e, usage.getLineNumber(), usage.getColumnNumber()));
         }
         return null;
diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
index 9d91fcf..7db4dc7 100644
--- a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
+++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
@@ -19,9 +19,8 @@
 package groovy.text.markup
 
 import groovy.transform.CompileStatic
-import org.codehaus.groovy.antlr.AntlrParserPlugin
-import org.codehaus.groovy.antlr.parser.GroovyLexer
-import org.codehaus.groovy.antlr.parser.GroovyRecognizer
+import org.apache.groovy.parser.antlr4.Antlr4ParserPlugin
+import org.apache.groovy.parser.antlr4.Antlr4PluginFactory
 import org.codehaus.groovy.ast.ASTNode
 import org.codehaus.groovy.ast.ClassCodeExpressionTransformer
 import org.codehaus.groovy.ast.ClassHelper
@@ -39,18 +38,16 @@ import org.codehaus.groovy.ast.expr.MethodCallExpression
 import org.codehaus.groovy.ast.expr.TupleExpression
 import org.codehaus.groovy.ast.expr.VariableExpression
 import org.codehaus.groovy.ast.stmt.EmptyStatement
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.control.ParserPluginFactory
 import org.codehaus.groovy.control.ResolveVisitor
 import org.codehaus.groovy.control.SourceUnit
 import org.codehaus.groovy.control.messages.SyntaxErrorMessage
-import org.codehaus.groovy.syntax.ParserException
-import org.codehaus.groovy.syntax.Reduction
 import org.codehaus.groovy.syntax.SyntaxException
 import org.codehaus.groovy.syntax.Types
 import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport
 import org.codehaus.groovy.transform.stc.TypeCheckingContext
 
-import java.util.concurrent.atomic.AtomicReference
-
 import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.isAssignment
 
@@ -178,23 +175,11 @@ class MarkupTemplateTypeCheckingExtension extends GroovyTypeCheckingExtensionSup
 
     @CompileStatic
     private static ClassNode buildNodeFromString(String option, TypeCheckingContext ctx) {
-        GroovyLexer lexer = new GroovyLexer(new StringReader(option))
-        final GroovyRecognizer rn = GroovyRecognizer.make(lexer)
-        rn.classOrInterfaceType(true);
-        final AtomicReference<ClassNode> ref = new AtomicReference<ClassNode>();
-        AntlrParserPlugin plugin = new AntlrParserPlugin() {
-            @Override
-            public ModuleNode buildAST(
-                    final SourceUnit sourceUnit,
-                    final ClassLoader classLoader, final Reduction cst) throws ParserException {
-                ref.set(makeTypeWithArguments(rn.getAST()));
-                return null;
-            }
-        };
-        plugin.buildAST(null, null, null);
-        ClassNode parsedNode = ref.get();
-        ClassNode dummyClass = new ClassNode("dummy", 0, ClassHelper.OBJECT_TYPE);
-        dummyClass.setModule(new ModuleNode(ctx.source));
+        Antlr4PluginFactory antlr4PluginFactory = (Antlr4PluginFactory) ParserPluginFactory.antlr4(CompilerConfiguration.DEFAULT)
+        Antlr4ParserPlugin antlr4ParserPlugin = (Antlr4ParserPlugin) antlr4PluginFactory.createParserPlugin()
+        ClassNode parsedNode = antlr4ParserPlugin.makeType(option)
+        ClassNode dummyClass = new ClassNode("dummy", 0, ClassHelper.OBJECT_TYPE)
+        dummyClass.setModule(new ModuleNode(ctx.source))
         MethodNode dummyMN = new MethodNode(
                 "dummy",
                 0,
@@ -203,16 +188,16 @@ class MarkupTemplateTypeCheckingExtension extends GroovyTypeCheckingExtensionSup
                 ClassNode.EMPTY_ARRAY,
                 EmptyStatement.INSTANCE
         )
-        dummyClass.addMethod(dummyMN);
+        dummyClass.addMethod(dummyMN)
         ResolveVisitor visitor = new ResolveVisitor(ctx.compilationUnit) {
             @Override
-            public void addError(final String msg, final ASTNode expr) {
+            void addError(final String msg, final ASTNode expr) {
                 ctx.errorCollector.addErrorAndContinue(new SyntaxErrorMessage(
                         new SyntaxException(msg + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()),
                         ctx.source)
-                );
+                )
             }
-        };
+        }
         visitor.startResolving(dummyClass, ctx.source)
         return dummyMN.getReturnType()
     }
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java
index fa6b381..44e76e5 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/Antlr4ParserPlugin.java
@@ -18,10 +18,18 @@
  */
 package org.apache.groovy.parser.antlr4;
 
+import groovy.lang.GroovyClassLoader;
 import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.ast.expr.DeclarationExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.stmt.ExpressionStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
 import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.control.ErrorCollector;
 import org.codehaus.groovy.control.ParserPlugin;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.control.io.ReaderSource;
@@ -32,6 +40,9 @@ import org.codehaus.groovy.syntax.Reduction;
 
 import java.io.IOException;
 import java.io.Reader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
 
 /**
  * A parser plugin for the new parser
@@ -77,4 +88,61 @@ public class Antlr4ParserPlugin implements ParserPlugin {
 
         return builder.buildAST();
     }
+
+    /**
+     * Create ClassNode instance for type string
+     *
+     * @param typeStr type string, e.g. List
+     * @return a {@link ClassNode} instance
+     * @since 3.0.0
+     */
+    public ClassNode makeType(String typeStr) {
+        SourceUnit sourceUnit =
+                new SourceUnit(
+                        "Script" + System.nanoTime(),
+                        typeStr + " v",
+                        compilerConfiguration,
+                        AccessController.doPrivileged(
+                                new PrivilegedAction<GroovyClassLoader>() {
+                                    @Override
+                                    public GroovyClassLoader run() {
+                                        return new GroovyClassLoader();
+                                    }
+                                }),
+                        new ErrorCollector(compilerConfiguration)
+                );
+        AstBuilder builder = new AstBuilder(sourceUnit, compilerConfiguration);
+        ModuleNode moduleNode = builder.buildAST();
+
+        List<Statement> statementList = moduleNode.getStatementBlock().getStatements();
+
+        Statement statement;
+        try {
+            statement = statementList.get(0);
+        } catch (IndexOutOfBoundsException e) {
+            throw new GroovyBugError(statementList + " is empty");
+        }
+
+        if (!(statement instanceof ExpressionStatement)) {
+            throw new GroovyBugError(statement + " is not an instance of ExpressionStatement");
+        }
+
+        ExpressionStatement expressionStatement = (ExpressionStatement) statement;
+        Expression expression = expressionStatement.getExpression();
+
+        if (!(expression instanceof DeclarationExpression)) {
+            throw new GroovyBugError(expression + " is not an instance of DeclarationExpression");
+        }
+
+        DeclarationExpression declarationExpression = (DeclarationExpression) expression;
+        Expression leftExpression = declarationExpression.getLeftExpression();
+
+        if (!(leftExpression instanceof VariableExpression)) {
+            throw new GroovyBugError(leftExpression + " is not an instance of VariableExpression");
+        }
+
+        VariableExpression variableExpression = (VariableExpression) leftExpression;
+
+        return variableExpression.getType();
+    }
 }