Commits

Tim Vernum  committed e0f9917

Add functional test suite

  • Participants
  • Parent commits f1cbd97

Comments (0)

Files changed (13)

File convert/source/java/main/org/adjective/syntactic/convert/j8to7/Convert7To8Visitor.java

-/*
- * ------------------------------------------------------------------------
- *  Copyright 2013 Tim Vernum
- *  ------------------------------------------------------------------------
- *  Licensed 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.adjective.syntactic.convert.j8to7;
-
-import org.adjective.syntactic.convert.j8to7.util.ClassFinder;
-import org.adjective.syntactic.convert.j8to7.util.Importer;
-import org.adjective.syntactic.convert.j8to7.util.VariableStack;
-import org.adjective.syntactic.parser.ast.*;
-import org.adjective.syntactic.parser.node.BaseNode;
-import org.adjective.syntactic.parser.node.ExpressionNode;
-import org.adjective.syntactic.parser.node.StatementNode;
-import org.adjective.syntactic.parser.node.VariableDeclarationNode;
-import org.adjective.syntactic.parser.type.JavaType;
-import org.adjective.syntactic.parser.util.DefaultVisitor;
-import org.adjective.syntactic.parser.util.ModifierSet;
-import org.adjective.syntactic.util.Pair;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Stack;
-
-public class Convert7To8Visitor extends DefaultVisitor<Object, Object>
-{
-    private final Stack<String> _className;
-    private final VariableStack _vars;
-    private final ClassFinder _classFinder;
-    private final Importer _importer;
-    private final LambdaConverter _lambdaConverter;
-    private final List<Pair<VariableDeclarationNode, String>> _toMarkFinal;
-
-    public Convert7To8Visitor()
-    {
-        _className = new Stack<String>();
-        _vars = new VariableStack();
-        _classFinder = new ClassFinder();
-        _importer = new Importer(_classFinder);
-        _lambdaConverter = new LambdaConverter(_importer, _classFinder);
-        _toMarkFinal = new ArrayList<Pair<VariableDeclarationNode, String>>();
-    }
-
-    @Override
-    public Object visit(final ASTCompilationUnit node, final Object data)
-    {
-        final Object val = super.visit(node, data);
-        for (Pair<VariableDeclarationNode, String> pair : _toMarkFinal)
-        {
-            markFinal(pair.tail, pair.head);
-        }
-        return val;
-    }
-
-    @Override
-    public Object visit(final ASTImportDeclaration node, final Object data)
-    {
-        _importer.add(node);
-        return super.visit(node, data);
-    }
-
-    private void markFinal(final String name, final VariableDeclarationNode node)
-    {
-        if (node.isMultiVariable())
-        {
-            Map<String, VariableDeclarationNode> split = node.split();
-            ASTBlock block = ((BaseNode) node).findAncestor(ASTBlock.class);
-            split.get(name).getModifiers().set(ModifierSet.Modifier.FINAL);
-            List<StatementNode> statements = new ArrayList<StatementNode>();
-            for (VariableDeclarationNode decl : split.values())
-            {
-                assert decl instanceof ASTLocalVariableDeclaration;
-                statements.add(new ASTVariableDeclarationStatement((ASTLocalVariableDeclaration) decl));
-            }
-            block.replace(node.jjtGetParent(), statements);
-        }
-        else
-        {
-            node.getModifiers().set(ModifierSet.Modifier.FINAL);
-        }
-    }
-
-    @Override
-    public Object visit(final ASTClassOrInterfaceDeclaration node, final Object data)
-    {
-        _className.push(node.getName().getIdentifier());
-        _classFinder.define(node);
-        try
-        {
-            return super.visit(node, data);
-        }
-        finally
-        {
-            _className.pop();
-        }
-    }
-
-    @Override
-    public Object visit(final ASTMethodDeclaration node, final Object data)
-    {
-        _vars.pushScope();
-        try
-        {
-            return super.visit(node, data);
-        }
-        finally
-        {
-            _vars.popScope();
-        }
-    }
-
-    @Override
-    public Object visit(final ASTBlock node, final Object data)
-    {
-        _vars.pushScope();
-        try
-        {
-            return super.visit(node, data);
-        }
-        finally
-        {
-            _vars.popScope();
-        }
-    }
-
-    @Override
-    public Object visit(final ASTFormalParameter node, final Object data)
-    {
-        _vars.store(node.getName().getIdentifier(), node);
-        return super.visit(node, data);
-    }
-
-    @Override
-    public Object visit(final ASTLocalVariableDeclaration node, final Object data)
-    {
-        for (ASTVariableDeclarator var : node.getVariables())
-        {
-            _vars.store(var.getIdentifier().getIdentifier(), node);
-
-            if (!var.hasInitializer())
-            {
-                continue;
-            }
-
-            final ExpressionNode init = var.getInitializer();
-            if (!init.is(ASTExpression.class))
-            {
-                continue;
-            }
-
-            ExpressionNode expr = init.as(ASTExpression.class).getBaseExpression();
-            if (!expr.is(ASTPrimaryExpression.class))
-            {
-                continue;
-            }
-
-            expr = expr.as(ASTPrimaryExpression.class).getPrefix();
-
-            if (!expr.is(ASTLambdaExpression.class))
-            {
-                continue;
-            }
-
-            final ASTLambdaExpression lambda = expr.as(ASTLambdaExpression.class);
-            final ExpressionNode convert = _lambdaConverter.convertLambda(lambda,
-                                                                          getType(node, var));
-            fixBody(lambda.getBody());
-            var.replaceInitializer(new ASTExpression(convert));
-        }
-
-        return super.visit(node, data);
-    }
-
-    private void fixBody(final ASTLambdaBody body)
-    {
-        body.jjtAccept(new DefaultVisitor<Object, Object>()
-        {
-            @Override
-            public Object visit(final ASTPrimaryExpression node, final Object data)
-            {
-                final ExpressionNode prefix = node.getPrefix();
-                if (node.jjtGetNumChildren() == 1)
-                {
-                    if (prefix.is(ASTQualifiedIdentifier.class))
-                    {
-                        String id = prefix.as(ASTQualifiedIdentifier.class).getName();
-                        markFinal(id);
-                    }
-                }
-                if (prefix.is(ASTThis.class))
-                {
-                    final ASTQualifiedIdentifier newPrefix = new ASTQualifiedIdentifier(_className.peek());
-                    final ASTMemberSuffix newSuffix = new ASTMemberSuffix(prefix.as(ASTThis.class));
-                    node.setTo(newPrefix, merge(newSuffix, node.getSuffixes()));
-                }
-                return super.visit(node, data);
-            }
-
-        }, null);
-    }
-
-    private void markFinal(final String var)
-    {
-        final VariableDeclarationNode node = _vars.get(var);
-        if (node == null)
-        {
-            return;
-        }
-        _toMarkFinal.add(new Pair<VariableDeclarationNode, String>(node, var));
-    }
-
-    private <T> Iterable<T> merge(final T first, final Iterable<T> rest)
-    {
-        final ArrayList<T> list = new ArrayList<T>();
-        list.add(first);
-        for (T t : rest)
-        {
-            list.add(t);
-        }
-        return list;
-    }
-
-    private JavaType getType(ASTLocalVariableDeclaration declaration, ASTVariableDeclarator variable)
-    {
-        return BaseNode.makeType(declaration.getTypeNode(), variable.getArraySuffix());
-    }
-
-}

File convert/source/java/main/org/adjective/syntactic/convert/j8to7/Convert8To7Visitor.java

+/*
+ * ------------------------------------------------------------------------
+ *  Copyright 2013 Tim Vernum
+ *  ------------------------------------------------------------------------
+ *  Licensed 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.adjective.syntactic.convert.j8to7;
+
+import org.adjective.syntactic.convert.j8to7.util.ClassFinder;
+import org.adjective.syntactic.convert.j8to7.util.Importer;
+import org.adjective.syntactic.convert.j8to7.util.VariableStack;
+import org.adjective.syntactic.parser.ast.*;
+import org.adjective.syntactic.parser.node.BaseNode;
+import org.adjective.syntactic.parser.node.ExpressionNode;
+import org.adjective.syntactic.parser.node.StatementNode;
+import org.adjective.syntactic.parser.node.VariableDeclarationNode;
+import org.adjective.syntactic.parser.type.JavaType;
+import org.adjective.syntactic.parser.util.DefaultVisitor;
+import org.adjective.syntactic.parser.util.ModifierSet;
+import org.adjective.syntactic.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+public class Convert8To7Visitor extends DefaultVisitor<Object, Object>
+{
+    private final Stack<String> _className;
+    private final VariableStack _vars;
+    private final ClassFinder _classFinder;
+    private final Importer _importer;
+    private final LambdaConverter _lambdaConverter;
+    private final List<Pair<VariableDeclarationNode, String>> _toMarkFinal;
+
+    public Convert8To7Visitor()
+    {
+        _className = new Stack<String>();
+        _vars = new VariableStack();
+        _classFinder = new ClassFinder();
+        _importer = new Importer(_classFinder);
+        _lambdaConverter = new LambdaConverter(_importer, _classFinder);
+        _toMarkFinal = new ArrayList<Pair<VariableDeclarationNode, String>>();
+    }
+
+    public void convert(final ASTCompilationUnit tree)
+    {
+        tree.jjtAccept(this, null);
+    }
+
+    @Override
+    public Object visit(final ASTCompilationUnit node, final Object data)
+    {
+        final Object val = super.visit(node, data);
+        for (Pair<VariableDeclarationNode, String> pair : _toMarkFinal)
+        {
+            markFinal(pair.tail, pair.head);
+        }
+        return val;
+    }
+
+    @Override
+    public Object visit(final ASTImportDeclaration node, final Object data)
+    {
+        _importer.add(node);
+        return super.visit(node, data);
+    }
+
+    private void markFinal(final String name, final VariableDeclarationNode node)
+    {
+        if (node.isMultiVariable())
+        {
+            Map<String, VariableDeclarationNode> split = node.split();
+            ASTBlock block = ((BaseNode) node).findAncestor(ASTBlock.class);
+            split.get(name).getModifiers().set(ModifierSet.Modifier.FINAL);
+            List<StatementNode> statements = new ArrayList<StatementNode>();
+            for (VariableDeclarationNode decl : split.values())
+            {
+                assert decl instanceof ASTLocalVariableDeclaration;
+                statements.add(new ASTVariableDeclarationStatement((ASTLocalVariableDeclaration) decl));
+            }
+            block.replace(node.jjtGetParent(), statements);
+        }
+        else
+        {
+            node.getModifiers().set(ModifierSet.Modifier.FINAL);
+        }
+    }
+
+    @Override
+    public Object visit(final ASTClassOrInterfaceDeclaration node, final Object data)
+    {
+        _className.push(node.getName().getIdentifier());
+        _classFinder.define(node);
+        try
+        {
+            return super.visit(node, data);
+        }
+        finally
+        {
+            _className.pop();
+        }
+    }
+
+    @Override
+    public Object visit(final ASTMethodDeclaration node, final Object data)
+    {
+        _vars.pushScope();
+        try
+        {
+            return super.visit(node, data);
+        }
+        finally
+        {
+            _vars.popScope();
+        }
+    }
+
+    @Override
+    public Object visit(final ASTBlock node, final Object data)
+    {
+        _vars.pushScope();
+        try
+        {
+            return super.visit(node, data);
+        }
+        finally
+        {
+            _vars.popScope();
+        }
+    }
+
+    @Override
+    public Object visit(final ASTFormalParameter node, final Object data)
+    {
+        _vars.store(node.getName().getIdentifier(), node);
+        return super.visit(node, data);
+    }
+
+    @Override
+    public Object visit(final ASTLocalVariableDeclaration node, final Object data)
+    {
+        for (ASTVariableDeclarator var : node.getVariables())
+        {
+            _vars.store(var.getIdentifier().getIdentifier(), node);
+
+            if (!var.hasInitializer())
+            {
+                continue;
+            }
+
+            final ExpressionNode init = var.getInitializer();
+            if (!init.is(ASTExpression.class))
+            {
+                continue;
+            }
+
+            ExpressionNode expr = init.as(ASTExpression.class).getBaseExpression();
+            if (!expr.is(ASTPrimaryExpression.class))
+            {
+                continue;
+            }
+
+            expr = expr.as(ASTPrimaryExpression.class).getPrefix();
+
+            if (!expr.is(ASTLambdaExpression.class))
+            {
+                continue;
+            }
+
+            final ASTLambdaExpression lambda = expr.as(ASTLambdaExpression.class);
+            final ExpressionNode convert = _lambdaConverter.convertLambda(lambda,
+                                                                          getType(node, var));
+            fixBody(lambda.getBody());
+            var.replaceInitializer(new ASTExpression(convert));
+        }
+
+        return super.visit(node, data);
+    }
+
+    private void fixBody(final ASTLambdaBody body)
+    {
+        body.jjtAccept(new DefaultVisitor<Object, Object>()
+        {
+            @Override
+            public Object visit(final ASTPrimaryExpression node, final Object data)
+            {
+                final ExpressionNode prefix = node.getPrefix();
+                if (node.jjtGetNumChildren() == 1)
+                {
+                    if (prefix.is(ASTQualifiedIdentifier.class))
+                    {
+                        String id = prefix.as(ASTQualifiedIdentifier.class).getName();
+                        markFinal(id);
+                    }
+                }
+                if (prefix.is(ASTThis.class))
+                {
+                    final ASTQualifiedIdentifier newPrefix = new ASTQualifiedIdentifier(_className.peek());
+                    final ASTMemberSuffix newSuffix = new ASTMemberSuffix(prefix.as(ASTThis.class));
+                    node.setTo(newPrefix, merge(newSuffix, node.getSuffixes()));
+                }
+                return super.visit(node, data);
+            }
+
+        }, null);
+    }
+
+    private void markFinal(final String var)
+    {
+        final VariableDeclarationNode node = _vars.get(var);
+        if (node == null)
+        {
+            return;
+        }
+        _toMarkFinal.add(new Pair<VariableDeclarationNode, String>(node, var));
+    }
+
+    private <T> Iterable<T> merge(final T first, final Iterable<T> rest)
+    {
+        final ArrayList<T> list = new ArrayList<T>();
+        list.add(first);
+        for (T t : rest)
+        {
+            list.add(t);
+        }
+        return list;
+    }
+
+    private JavaType getType(ASTLocalVariableDeclaration declaration, ASTVariableDeclarator variable)
+    {
+        return BaseNode.makeType(declaration.getTypeNode(), variable.getArraySuffix());
+    }
+
+}

File convert/source/java/main/org/adjective/syntactic/convert/j8to7/Main.java

         BaseNode ast = parse(filename);
         if (ast != null)
         {
-            ast.jjtAccept(new Convert7To8Visitor(), null);
+            ast.jjtAccept(new Convert8To7Visitor(), null);
             ast.jjtAccept(new PrintSourceVisitor(), System.out);
         }
     }

File convert/source/java/test/org/adjective/syntactic/convert/j8to7/functional/ConvertFunctionalTest.java

+/* ------------------------------------------------------------------------
+ * Copyright 2013 Tim Vernum
+ * ------------------------------------------------------------------------
+ * Licensed 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.adjective.syntactic.convert.j8to7.functional;
+
+import org.adjective.syntactic.convert.j8to7.Convert8To7Visitor;
+import org.adjective.syntactic.parser.ast.ASTCompilationUnit;
+import org.adjective.syntactic.parser.jj.JavaParser;
+import org.adjective.syntactic.parser.util.PrintSourceVisitor;
+import org.adjective.syntactic.util.IOUtil;
+import org.junit.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class ConvertFunctionalTest
+{
+    @org.junit.Test
+    public void testConversions() throws Exception
+    {
+        File root = new File("convert");
+        if (!root.exists())
+        {
+            root = new File(".");
+        }
+        final File directory = new File(root, "source/resource/test/functional/");
+        if (!directory.exists())
+        {
+            Assert.fail("Directory '" + directory.getAbsolutePath() + "' does not exist");
+        }
+        final File[] files = directory.listFiles();
+        if (files == null)
+        {
+            return;
+        }
+        for (File file : files)
+        {
+            if (isJavaSource(file))
+            {
+                File expected = new File(file.getAbsolutePath() + ".convert");
+                convertAndVerify(file, expected);
+            }
+        }
+    }
+
+    private boolean isJavaSource(final File file)
+    {
+        return file.isFile() && file.canRead() && file.getName().endsWith(".java");
+    }
+
+    private void convertAndVerify(final File input, final File expected) throws IOException
+    {
+        final ASTCompilationUnit ast = JavaParser.process(input);
+        if (!expected.exists())
+        {
+            System.err.println("Output '" + expected.getAbsolutePath() + "' for '" + input + "' does not exist");
+            return;
+        }
+        System.err.println("Running test: " + input);
+        new Convert8To7Visitor().convert(ast);
+        final ByteArrayOutputStream output = new ByteArrayOutputStream();
+        new PrintSourceVisitor().print(ast, output);
+        final byte[] read = IOUtil.read(new FileInputStream(expected));
+        Assert.assertEquals(new String(read), new String(output.toByteArray()));
+    }
+}

File convert/source/resource/test/functional/000-Blank.java

Empty file added.

File convert/source/resource/test/functional/000-Blank.java.convert

Empty file added.

File convert/source/resource/test/functional/001-EmptyClass.java

+public class Foo {
+}

File convert/source/resource/test/functional/001-EmptyClass.java.convert

+public class Foo {
+}

File convert/source/resource/test/functional/002-SimpleLambda.java

+public class X {
+
+    public Runnable getRunnable() {
+        Runnable r = () -> { } ;
+        return r;
+    }
+
+}
+

File convert/source/resource/test/functional/002-SimpleLambda.java.convert

+public class X {
+  public Runnable getRunnable() {
+    Runnable r = new Runnable() {
+      public void run() {
+      }
+    }
+;
+    return r;
+  }
+}

File parser/source/grammar/java.jjt

         catch(Exception e) { e.printStackTrace(); }
     }
 
-    public static Node processStdin()
+    public static ASTCompilationUnit processStdin()
     {
-        return process( new JavaParser(System.in) );
+        return process( System.in );
     }
 
-    public static Node process(String file)
+    public static ASTCompilationUnit process(String file)
+    {
+        return process(new java.io.File(file));
+    }
+
+    public static ASTCompilationUnit process(File file) 
     {
         try 
         {
-            return process(new JavaParser(new java.io.FileInputStream(file)));
+            return process(new java.io.FileInputStream(file));
         }
         catch (java.io.FileNotFoundException e)
         {
-            System.err.println("Java Parser Version 1.2:  File " + file + " not found.");
+            System.err.println("Java Parser Version 1.2:  File " + file.getAbsolutePath() + " not found.");
             return null;
         }
     }
 
-    private static Node process(JavaParser parser)
+    public static ASTCompilationUnit process(InputStream input)
+    {
+        return process(new JavaParser(input));
+    }
+
+    private static ASTCompilationUnit process(JavaParser parser)
     {
         try
         {
-            Node node = parser.CompilationUnit();
+            ASTCompilationUnit node = parser.CompilationUnit();
             return node;
         }
         catch (ParseException e)
         }
     }
 
-    public static Node main(String args[]) 
+    public static ASTCompilationUnit main(String args[]) 
     {
         JavaParser parser;
         if (args.length == 0)
  * Program structuring syntax follows.
  */
 
-Node CompilationUnit():
+ASTCompilationUnit CompilationUnit():
 {}
 {
   [ LOOKAHEAD( Annotations() "package" ) PackageDeclaration() ]

File parser/source/java/parser/org/adjective/syntactic/parser/util/PrintSourceVisitor.java

 import org.adjective.syntactic.parser.node.HasTokens;
 
 import java.io.IOException;
+import java.io.OutputStream;
 import java.io.PrintStream;
 
 public class PrintSourceVisitor implements JavaParserVisitor<Object, PrintStream>
 {
     private long _indent = 0;
 
+    public void print(final ASTCompilationUnit ast, final OutputStream output)
+    {
+        ast.jjtAccept(this, new PrintStream(output));
+    }
+
     private CharSequence getIndentString()
     {
         final StringBuilder builder = new StringBuilder();
     {
         _indent++;
         out.println("{");
-        printIndent(out);
-        printListSource(out, node.getElements(), "");
+        if (!node.isEmpty())
+        {
+            printIndent(out);
+            printListSource(out, node.getElements(), "");
+        }
         _indent--;
         printIndent(out);
         out.println("}");
             node.getConstructorArguments().jjtAccept(this, out);
             if (node.isAnonymousClass())
             {
+                out.print(' ');
                 node.getClassBody().jjtAccept(this, out);
             }
         }
     {
         out.println("{");
         _indent++;
-        printIndent(out);
-        printListSource(out, node.statements(), getIndentString());
+        if (!node.isEmpty())
+        {
+            printIndent(out);
+            printListSource(out, node.statements(), getIndentString());
+        }
         _indent--;
         printIndent(out);
         out.println("}");
         node.childrenAccept(this, out);
         return null;
     }
+
 }

File parser/source/java/parser/org/adjective/syntactic/util/IOUtil.java

+/* ------------------------------------------------------------------------
+ * Copyright 2013 Tim Vernum
+ * ------------------------------------------------------------------------
+ * Licensed 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.adjective.syntactic.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class IOUtil
+{
+    public static byte[] read(final InputStream input) throws IOException
+    {
+        final ByteArrayOutputStream output = new ByteArrayOutputStream();
+        copy(input, output);
+        return output.toByteArray();
+    }
+
+    private static void copy(final InputStream input, final OutputStream output) throws IOException
+    {
+        byte[] buffer = new byte[8192];
+        for (; ; )
+        {
+            int len = input.read(buffer);
+            if (len == -1)
+            {
+                return;
+            }
+            output.write(buffer, 0, len);
+        }
+    }
+}