Skip to content

Commit

Permalink
Fix for #1042: adjust offsets of qualified types in catch and instanceof
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Feb 26, 2020
1 parent f306477 commit dc82819
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2019 the original author or authors.
* Copyright 2009-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -24,11 +24,12 @@

import org.codehaus.groovy.antlr.LocationSupport;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.expr.DeclarationExpression;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.TryCatchStatement;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.ErrorCollector;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration;
import org.eclipse.jdt.groovy.core.util.ReflectionUtils;
Expand Down Expand Up @@ -60,14 +61,13 @@ public void testLocationSupport() throws Exception {
@Test
public void testParserSourceLocationsBlock() throws Exception {
String content = "def x = 7\n x++\n def y = []";
SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(0, module.getStatementBlock().getStart());
Expand All @@ -83,29 +83,27 @@ public void testParserSourceLocationsBlock() throws Exception {
@Test
public void testParserSourceLocationsEmpty() throws Exception {
String content = "";
SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
}

@Test
public void testParserSourceLocationsOneLine() throws Exception {
String content = "def x = 7";
SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(0, module.getStatementBlock().getStart());
Expand All @@ -117,14 +115,13 @@ public void testParserSourceLocationsOneLine() throws Exception {
@Test
public void testParserSourceLocationsNewLine() throws Exception {
String content = "def x = 7\n";
SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals("".length(), module.getStatementBlock().getStart());
Expand All @@ -136,14 +133,13 @@ public void testParserSourceLocationsNewLine() throws Exception {
@Test
public void testParserSourceLocationsClass() throws Exception {
String content = "class X {\n}";
SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(0, ((ASTNode) module.getClasses().get(0)).getStart());
Expand All @@ -153,14 +149,13 @@ public void testParserSourceLocationsClass() throws Exception {
@Test
public void testParserSourceLocationsMethod() throws Exception {
String content = "def x() { \n\n\n\n\n\n\n}";
SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(0, ((ASTNode) module.getMethods().get(0)).getStart());
Expand All @@ -172,14 +167,13 @@ public void testParserSourceLocationsMethod() throws Exception {
@Test
public void testParserSourceLocationsMethod2() throws Exception {
String content = "def \"x \" () { \n\n\n\n\n\n\n}";
SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(0, ((ASTNode) module.getMethods().get(0)).getStart());
Expand All @@ -188,18 +182,52 @@ public void testParserSourceLocationsMethod2() throws Exception {
assertEquals(content.length(), ((ASTNode) module.getMethods().get(0)).getEnd());
}

@Test
public void testParserSourceLocationsCatchStatement1() throws Exception {
String content = "try {} catch (Exception ex) {}";
// ^14 ^23

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();

TryCatchStatement tryCatch = (TryCatchStatement) sourceUnit.getAST().getStatementBlock().getStatements().get(0);
ClassNode exceptionType = tryCatch.getCatchStatement(0).getVariable().getType();

assertEquals(content.indexOf("Exception"), exceptionType.getStart());
assertEquals(content.indexOf("Exception"), exceptionType.getNameStart2());
assertEquals(content.indexOf("Exception") + 9, exceptionType.getEnd());
}

@Test
public void testParserSourceLocationsCatchStatement2() throws Exception {
String content = "try {} catch (java.lang.Exception ex) {}";
// ^14 ^33

SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();

TryCatchStatement tryCatch = (TryCatchStatement) sourceUnit.getAST().getStatementBlock().getStatements().get(0);
ClassNode exceptionType = tryCatch.getCatchStatement(0).getVariable().getType();

assertEquals(content.indexOf("java."), exceptionType.getStart());
assertEquals(content.indexOf("Exception"), exceptionType.getNameStart2());
assertEquals(content.indexOf("Exception") + 9, exceptionType.getEnd());
}

@Test
public void testParserSourceLocationsClassMethodStatement() throws Exception {
String content = "def x = 7\n x++\n def y = []\ndef z() { \n\n\n\n\n\n\n}\nclass X {\n}";

SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));
SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(0, module.getStatementBlock().getStart());
Expand All @@ -221,25 +249,22 @@ public void testParserSourceLocationsClassMethodStatement() throws Exception {
public void testGRECLIPSE887_ImportStatements() throws Exception {
String content = "import java.util.List\nimport java.lang.*\nimport javax.swing.text.html.HTML.A\nimport javax.swing.text.html.HTML.*";

SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));
SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
final ModuleNode module = sourceUnit.getAST();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(0, module.getImport("List").getStart());
assertEquals("import java.util.List".length(), module.getImport("List").getEnd());
assertEquals("import java.util.List\n".length(), module.getStarImports().get(0).getStart());
assertEquals("import java.util.List\nimport java.lang.*".length(), module.getStarImports().get(0).getEnd());
assertEquals("import java.util.List\nimport java.lang.*\n".length(), module.getImport("A").getStart());
assertEquals("import java.util.List\nimport java.lang.*\nimport javax.swing.text.html.HTML.A".length(), module.getImport("A").getEnd());
assertEquals("import java.util.List\nimport java.lang.*\nimport javax.swing.text.html.HTML.A\n".length(), module.getStarImports().get(1).getStart());
assertEquals("import java.util.List\nimport java.lang.*\nimport javax.swing.text.html.HTML.A\nimport javax.swing.text.html.HTML.*".length(),
module.getStarImports().get(1).getEnd());
assertEquals(content.indexOf("List") + 4, module.getImport("List").getEnd());
assertEquals(content.indexOf("import java.lang.*"), module.getStarImports().get(0).getStart());
assertEquals(content.indexOf("import java.lang.*") + 18, module.getStarImports().get(0).getEnd());
assertEquals(content.indexOf("import javax.swing.text.html.HTML.A"), module.getImport("A").getStart());
assertEquals(content.indexOf("import javax.swing.text.html.HTML.A") + 35, module.getImport("A").getEnd());
assertEquals(content.indexOf("import javax.swing.text.html.HTML.*"), module.getStarImports().get(1).getStart());
assertEquals(content.length(), module.getStarImports().get(1).getEnd());

// now test against the compilation unit declaration
GroovyCompilationUnitDeclaration cud = new GroovyCompilationUnitDeclaration(null, null, -1, null, null, null) {
Expand All @@ -265,14 +290,12 @@ public void testUnicodeEscapes1() throws Exception {
String escapeSequence = "/*\\u00E9*/ ";
String content = escapeSequence + "def x = 7";

SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));
SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(escapeSequence.length(), ((ASTNode) module.getStatementBlock().getStatements().get(0)).getStart());
Expand All @@ -284,14 +307,12 @@ public void testUnicodeEscapes2() throws Exception {
String escapeSequence = "/*\\u00E9*/ ";
String content = escapeSequence + "\n\n\ndef x = 7";

SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));
SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(content.indexOf("def"), ((ASTNode) module.getStatementBlock().getStatements().get(0)).getStart());
Expand All @@ -303,14 +324,12 @@ public void testUnicodeEscapes3() throws Exception {
String escapeSequence = "/*\\u00E9\\u00E9\\u00E9\\u00E9\\u00E9\\u00E9\\u00E9\\u00E9\\u00E9*/";
String content = escapeSequence + "\n\n\ndef /*\\u00E9*/x = /*\\u00E9*/7";

SourceUnit sourceUnit = new SourceUnit("Foo", content,
CompilerConfiguration.DEFAULT, new GroovyClassLoader(), new ErrorCollector(CompilerConfiguration.DEFAULT));
SourceUnit sourceUnit = new SourceUnit("script", content, CompilerConfiguration.DEFAULT, new GroovyClassLoader(), null);
sourceUnit.parse();
sourceUnit.completePhase();
sourceUnit.convert();
ModuleNode module = sourceUnit.getAST();

// now check locations
assertEquals(0, module.getStart());
assertEquals(content.length(), module.getEnd());
assertEquals(content.indexOf("def"), ((ASTNode) module.getStatementBlock().getStatements().get(0)).getStart());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3491,11 +3491,13 @@ protected Expression gstring(AST gstringNode) {
return gStringExpression;
}

/* GRECLIPSE edit
protected ClassNode type(AST typeNode) {
// TODO intern types?
// TODO configureAST(...)
return buildName(typeNode.getFirstChild());
}
*/

public static String qualifiedName(AST qualifiedNameNode) {
if (isType(IDENT, qualifiedNameNode)) {
Expand Down Expand Up @@ -3689,14 +3691,11 @@ protected ClassNode makeType(AST typeNode) {
return answer;
}

/**
* Extracts an identifier from the Antlr AST and then performs a name resolution
* to see if the given name is a type from imports, aliases or newly created classes
*/
protected ClassNode buildName(AST node) {
if (isType(TYPE, node)) {
node = node.getFirstChild();
}
/* GRECLIPSE edit
ClassNode answer = null;
if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
answer = ClassHelper.make(qualifiedName(node));
Expand All @@ -3720,6 +3719,34 @@ protected ClassNode buildName(AST node) {
configureAST(answer, node);
return answer;
}
*/
if (isType(ARRAY_DECLARATOR, node.getNextSibling()) || isType(INDEX_OP, node.getNextSibling())) {
throw new ASTRuntimeException(node, "Unexpected '[' sibling in type name");
}
if (isType(ARRAY_DECLARATOR, node) || isType(INDEX_OP, node)) {
ClassNode answer = buildName(node.getFirstChild()).makeArray();
configureAST(answer, node);
return answer;
}

String name;
if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
name = qualifiedName(node);
} else {
name = node.getText();
}

ClassNode answer = makeClassNode(name);
configureAST(answer, node);
if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
GroovySourceAST type = (GroovySourceAST) node.getFirstChild().getNextSibling();
answer.setLastLineNumber(type.getLineLast());
answer.setLastColumnNumber(type.getColumnLast());
answer.setNameStart2(locations.findOffset(type.getLine(), type.getColumn()));
answer.setEnd(locations.findOffset(type.getLineLast(), type.getColumnLast()));
}
return answer;
// GRECLIPSE end
}

protected boolean isPrimitiveTypeLiteral(AST node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3588,6 +3588,7 @@ protected ClassNode buildName(AST node) {
} else {
name = node.getText();
}
/* GRECLIPSE edit
ClassNode answer = ClassHelper.make(name);
AST nextSibling = node.getNextSibling();
if (isType(ARRAY_DECLARATOR, nextSibling) || isType(INDEX_OP, nextSibling)) {
Expand All @@ -3596,6 +3597,22 @@ protected ClassNode buildName(AST node) {
configureAST(answer, node);
return answer;
}
*/
if (isType(ARRAY_DECLARATOR, node.getNextSibling()) || isType(INDEX_OP, node.getNextSibling())) {
throw new ASTRuntimeException(node, "Unexpected '[' sibling in type name");
}

ClassNode answer = makeClassNode(name);
configureAST(answer, node);
if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
GroovySourceAST type = (GroovySourceAST) node.getFirstChild().getNextSibling();
answer.setLastLineNumber(type.getLineLast());
answer.setLastColumnNumber(type.getColumnLast());
answer.setNameStart2(locations.findOffset(type.getLine(), type.getColumn()));
answer.setEnd(locations.findOffset(type.getLineLast(), type.getColumnLast()));
}
return answer;
// GRECLIPSE end
}

protected boolean isPrimitiveTypeLiteral(AST node) {
Expand Down
Loading

0 comments on commit dc82819

Please sign in to comment.