You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2019/11/20 19:23:44 UTC

[groovy] branch GROOVY_3_0_X updated: create parser-agnostic API for parsing snippet

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

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


View the commit online:
https://github.com/apache/groovy/commit/92bc52a750fb30c34eada82fb68418378e25c490

The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 92bc52a  create parser-agnostic API for parsing snippet
92bc52a is described below

commit 92bc52a750fb30c34eada82fb68418378e25c490
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Nov 20 13:01:44 2019 -0600

    create parser-agnostic API for parsing snippet
---
 .../org/codehaus/groovy/ast/tools/Antlr2Utils.java | 65 ----------------------
 .../org/codehaus/groovy/ast/tools/Antlr4Utils.java | 36 ------------
 .../codehaus/groovy/ast/tools/GenericsUtils.java   | 34 +++++------
 .../org/codehaus/groovy/control/ParserPlugin.java  | 13 ++++-
 .../MarkupTemplateTypeCheckingExtension.groovy     | 14 ++---
 .../groovy/parser/antlr4/Antlr4ParserPlugin.java   | 62 ---------------------
 6 files changed, 29 insertions(+), 195 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/Antlr2Utils.java b/src/main/java/org/codehaus/groovy/ast/tools/Antlr2Utils.java
deleted file mode 100644
index 5e04372..0000000
--- a/src/main/java/org/codehaus/groovy/ast/tools/Antlr2Utils.java
+++ /dev/null
@@ -1,65 +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.
- */
-package org.codehaus.groovy.ast.tools;
-
-import antlr.RecognitionException;
-import antlr.TokenStreamException;
-import groovy.lang.GroovyRuntimeException;
-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.ClassNode;
-import org.codehaus.groovy.ast.ModuleNode;
-import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.syntax.ParserException;
-import org.codehaus.groovy.syntax.Reduction;
-
-import java.io.StringReader;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Utilities for working with the Antlr2 parser
- *
- * @deprecated will be removed when antlr2 parser is removed
- */
-@Deprecated
-public class Antlr2Utils {
-    private Antlr2Utils() {
-    }
-
-    public static ClassNode parse(String option) {
-        GroovyLexer lexer = new GroovyLexer(new StringReader("DummyNode<" + option + ">"));
-        try {
-            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);
-            return ref.get();
-        } catch (RecognitionException | TokenStreamException | ParserException e) {
-            throw new GroovyRuntimeException("Unable to parse '" + option + "'", e);
-        }
-    }
-}
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/Antlr4Utils.java b/src/main/java/org/codehaus/groovy/ast/tools/Antlr4Utils.java
deleted file mode 100644
index 05395ee..0000000
--- a/src/main/java/org/codehaus/groovy/ast/tools/Antlr4Utils.java
+++ /dev/null
@@ -1,36 +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.
- */
-package org.codehaus.groovy.ast.tools;
-
-import org.apache.groovy.parser.antlr4.Antlr4ParserPlugin;
-import org.apache.groovy.parser.antlr4.Antlr4PluginFactory;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.control.ParserPluginFactory;
-
-public class Antlr4Utils {
-    private Antlr4Utils() {
-    }
-
-    public static ClassNode parse(String option, CompilerConfiguration configuration) {
-        Antlr4PluginFactory antlr4PluginFactory = (Antlr4PluginFactory) ParserPluginFactory.antlr4(configuration);
-        Antlr4ParserPlugin antlr4ParserPlugin = (Antlr4ParserPlugin) antlr4PluginFactory.createParserPlugin();
-        return antlr4ParserPlugin.makeType(option);
-    }
-}
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 8675c25..1b20724 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -18,11 +18,9 @@
  */
 package org.codehaus.groovy.ast.tools;
 
-import groovy.lang.GroovyRuntimeException;
 import groovy.lang.Tuple2;
 import groovy.transform.stc.IncorrectTypeHintException;
 import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.antlr.AntlrParserPluginFactory;
 import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
@@ -30,9 +28,11 @@ import org.codehaus.groovy.ast.GenericsType;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.expr.DeclarationExpression;
 import org.codehaus.groovy.ast.stmt.EmptyStatement;
+import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.CompilerConfiguration;
+import org.codehaus.groovy.control.ParserPlugin;
 import org.codehaus.groovy.control.ResolveVisitor;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.runtime.memoize.ConcurrentSoftCache;
@@ -580,32 +580,24 @@ public class GenericsUtils {
         }
     }
 
-    public static ClassNode[] parseClassNodesFromString(
-            final String option,
-            final SourceUnit sourceUnit,
-            final CompilationUnit compilationUnit,
-            final MethodNode mn,
-            final ASTNode usage) {
-
+    public static ClassNode[] parseClassNodesFromString(final String option, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final MethodNode mn, final ASTNode usage) {
         try {
-            // for parsing just class names old and new parser should be the same but let's stick to the correct parser any way
-            boolean oldParserEnabled = compilationUnit.getConfiguration().getPluginFactory() instanceof AntlrParserPluginFactory;
-            ClassNode parsedNode = oldParserEnabled ?
-                    Antlr2Utils.parse(option) :
-                    Antlr4Utils.parse("DummyNode<" + option + ">", compilationUnit.getConfiguration());
+            ModuleNode moduleNode = ParserPlugin.buildAST("Dummy<" + option + "> dummy;", compilationUnit.getClassLoader(), compilationUnit.getConfiguration(), null);
+            DeclarationExpression dummyDeclaration = (DeclarationExpression) ((ExpressionStatement) moduleNode.getStatementBlock().getStatements().get(0)).getExpression();
 
             // the returned node is DummyNode<Param1, Param2, Param3, ...)
-            GenericsType[] parsedNodeGenericsTypes = parsedNode.getGenericsTypes();
-            if (parsedNodeGenericsTypes == null) {
+            ClassNode dummyNode = dummyDeclaration.getLeftExpression().getType();
+            GenericsType[] dummyNodeGenericsTypes = dummyNode.getGenericsTypes();
+            if (dummyNodeGenericsTypes == null) {
                 return null;
             }
-            ClassNode[] signature = new ClassNode[parsedNodeGenericsTypes.length];
-            for (int i = 0; i < parsedNodeGenericsTypes.length; i++) {
-                final GenericsType genericsType = parsedNodeGenericsTypes[i];
+            ClassNode[] signature = new ClassNode[dummyNodeGenericsTypes.length];
+            for (int i = 0, n = dummyNodeGenericsTypes.length; i < n; i += 1) {
+                final GenericsType genericsType = dummyNodeGenericsTypes[i];
                 signature[i] = resolveClassNode(sourceUnit, compilationUnit, mn, usage, genericsType.getType());
             }
             return signature;
-        } catch (GroovyRuntimeException e) {
+        } catch (Exception | LinkageError e) {
             sourceUnit.addError(new IncorrectTypeHintException(mn, e, usage.getLineNumber(), usage.getColumnNumber()));
         }
         return null;
diff --git a/src/main/java/org/codehaus/groovy/control/ParserPlugin.java b/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
index 9b298d8..1d4f488 100644
--- a/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
@@ -18,19 +18,28 @@
  */
 package org.codehaus.groovy.control;
 
+import groovy.lang.GroovyClassLoader;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.codehaus.groovy.syntax.ParserException;
 import org.codehaus.groovy.syntax.Reduction;
+import org.codehaus.groovy.util.CharSequenceReader;
 
 import java.io.Reader;
 
 /**
- * A simple extension point to allow us to switch between the classic Groovy parser and the new Antlr based parser
- * 
+ * A simple extension point to allow us to switch between the classic Groovy parser and the new Antlr based parser(s).
  */
 public interface ParserPlugin {
 
     Reduction parseCST(SourceUnit sourceUnit, Reader reader) throws CompilationFailedException;
 
     ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException;
+
+    static ModuleNode buildAST(CharSequence source, GroovyClassLoader loader, CompilerConfiguration config, ErrorCollector errors) throws ParserException {
+        String scriptName = "Script" + System.nanoTime() + ".groovy";
+        SourceUnit sourceUnit = new SourceUnit(scriptName, source.toString(), config, loader, errors);
+
+        ParserPlugin parserPlugin = config.getPluginFactory().createParserPlugin();
+        return parserPlugin.buildAST(sourceUnit, loader, parserPlugin.parseCST(sourceUnit, new CharSequenceReader(source)));
+    }
 }
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 ea302da..697e0b4 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,7 +19,6 @@
 package groovy.text.markup
 
 import groovy.transform.CompileStatic
-import org.codehaus.groovy.antlr.AntlrParserPluginFactory
 import org.codehaus.groovy.ast.ASTNode
 import org.codehaus.groovy.ast.ClassCodeExpressionTransformer
 import org.codehaus.groovy.ast.ClassHelper
@@ -32,14 +31,14 @@ import org.codehaus.groovy.ast.expr.ArrayExpression
 import org.codehaus.groovy.ast.expr.BinaryExpression
 import org.codehaus.groovy.ast.expr.ClosureExpression
 import org.codehaus.groovy.ast.expr.ConstantExpression
+import org.codehaus.groovy.ast.expr.DeclarationExpression
 import org.codehaus.groovy.ast.expr.Expression
 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.ast.tools.Antlr2Utils
-import org.codehaus.groovy.ast.tools.Antlr4Utils
-import org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.ast.stmt.ExpressionStatement
+import org.codehaus.groovy.control.ParserPlugin
 import org.codehaus.groovy.control.ResolveVisitor
 import org.codehaus.groovy.control.SourceUnit
 import org.codehaus.groovy.control.messages.SyntaxErrorMessage
@@ -175,11 +174,8 @@ class MarkupTemplateTypeCheckingExtension extends GroovyTypeCheckingExtensionSup
 
     @CompileStatic
     private static ClassNode buildNodeFromString(String option, TypeCheckingContext ctx) {
-        // for parsing just class names old and new parser should be the same but let's stick to the correct parser any way
-        boolean oldParserEnabled = CompilerConfiguration.DEFAULT.pluginFactory instanceof AntlrParserPluginFactory
-        ClassNode parsedNode = oldParserEnabled ?
-                Antlr2Utils.parse(option) :
-                Antlr4Utils.parse(option, CompilerConfiguration.DEFAULT)
+        def moduleNode = ParserPlugin.buildAST("Dummy<$option> dummy;", ctx.compilationUnit.classLoader, ctx.compilationUnit.configuration, ctx.errorCollector)
+        ClassNode parsedNode = ((DeclarationExpression) ((ExpressionStatement) moduleNode.statementBlock.statements[0]).expression).leftExpression.type
         ClassNode dummyClass = new ClassNode("dummy", 0, OBJECT_TYPE)
         dummyClass.setModule(new ModuleNode(ctx.source))
         MethodNode dummyMN = new MethodNode(
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 fa6aa7b..fa6b381 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,18 +18,10 @@
  */
 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;
@@ -40,9 +32,6 @@ 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
@@ -88,55 +77,4 @@ 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(),
-                        "final " + typeStr + " v",
-                        compilerConfiguration,
-                        AccessController.doPrivileged((PrivilegedAction<GroovyClassLoader>) GroovyClassLoader::new),
-                        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();
-    }
 }