Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue 3631 NameExpr.resolve() does not take end of inner block scopes into account #3613

Merged
merged 5 commits into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ protected void writeNonMetaProperties(Node node, JsonGenerator generator) {
}

protected void writeRange(Node node, JsonGenerator generator) {
if (node.getRange().isPresent()) {
if (node.hasRange()) {
Range range = node.getRange().get();
generator.writeStartObject(JsonNode.RANGE.propertyKey);
generator.write(JsonRange.BEGIN_LINE.propertyKey, range.begin.line);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ void testNonMetaProperties() {

CompilationUnit deserialized = (CompilationUnit) deserializer.deserializeObject(Json.createReader(new StringReader(serialized)));

assertTrue(deserialized.getRange().isPresent());
assertTrue(deserialized.hasRange());
Range range = deserialized.getRange().get();
assertEquals(1, range.begin.line);
assertEquals(1, range.begin.line);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void rangeOfAnnotationMemberDeclarationIsCorrect() {
String code = "@interface AD { String foo(); }";
CompilationUnit cu = parse(code);
AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
assertTrue(memberDeclaration.getRange().isPresent());
assertTrue(memberDeclaration.hasRange());
assertEquals(new Range(new Position(1, 17), new Position(1, 29)), memberDeclaration.getRange().get());
}

Expand All @@ -76,7 +76,7 @@ void testSourcePositionsWithUnicodeEscapes() {
String code = "@interface AD \\u007B String foo(); \\u007D";
CompilationUnit cu = parseWithUnicodeEscapes(code).getResult().get();
AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
assertTrue(memberDeclaration.getRange().isPresent());
assertTrue(memberDeclaration.hasRange());
assertEquals(new Range(new Position(1, 22), new Position(1, 34)), memberDeclaration.getRange().get());
}

Expand All @@ -102,7 +102,7 @@ void rangeOfAnnotationMemberDeclarationWithArrayTypeIsCorrect() {
String code = "@interface AD { String[] foo(); }";
CompilationUnit cu = parse(code);
AnnotationMemberDeclaration memberDeclaration = cu.getAnnotationDeclarationByName("AD").get().getMember(0).asAnnotationMemberDeclaration();
assertTrue(memberDeclaration.getRange().isPresent());
assertTrue(memberDeclaration.hasRange());
assertEquals(new Range(new Position(1, 17), new Position(1, 31)), memberDeclaration.getRange().get());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import static com.github.javaparser.utils.CodeGenerationUtils.f;
import static com.github.javaparser.utils.Utils.SYSTEM_EOL;
import static com.github.javaparser.utils.Utils.assertNotNull;

import java.util.List;
import java.util.Optional;

import com.github.javaparser.ast.Generated;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ public void addComment(Comment comment) {
}

public boolean contains(Comment comment) {
if (!comment.getRange().isPresent()) {
if (!comment.hasRange()) {
return false;
}
Range commentRange = comment.getRange().get();
for (Comment c : getComments()) {
if (!c.getRange().isPresent()) {
if (!c.hasRange()) {
return false;
}
Range cRange = c.getRange().get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,7 @@ private void printOrphanCommentsEnding(final Node node) {
if (configuration.isIgnoreComments()) return;

// extract all nodes for which the position/range is indicated to avoid to skip orphan comments
List<Node> everything = node.getChildNodes().stream().filter(n->n.getRange().isPresent()).collect(Collectors.toList());
List<Node> everything = node.getChildNodes().stream().filter(n->n.hasRange()).collect(Collectors.toList());
sortByBeginPosition(everything);
if (everything.isEmpty()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public boolean equals(Object other) {
// because we can have nodes with the same content but in different lines
// in this case we consider that nodes are not equals
return this.node.equals(cpi.node)
&& this.node.getRange().isPresent() && cpi.node.getRange().isPresent()
&& this.node.hasRange() && cpi.node.hasRange()
&& this.node.getRange().get().contains(cpi.node.getRange().get());
}
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ private static Optional<Node> findNodeForToken(Node node, Range tokenRange) {
if (node.isPhantom()) {
return Optional.empty();
}
if(!node.getRange().isPresent()) {
if(!node.hasRange()) {
return Optional.empty();
}
if (!node.getRange().get().contains(tokenRange)) {
Expand All @@ -403,7 +403,7 @@ private static void storeInitialTextForOneNode(Node node, List<JavaToken> nodeTo
List<Pair<Range, TextElement>> elements = new LinkedList<>();
for (Node child : node.getChildNodes()) {
if (!child.isPhantom()) {
if (!child.getRange().isPresent()) {
if (!child.hasRange()) {
throw new RuntimeException("Range not present on node " + child);
}
elements.add(new Pair<>(child.getRange().get(), new ChildTextElement(child)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ public static boolean areInOrder(Node a, Node b, boolean ignoringAnnotations) {
}

private static int compare(Node a, Node b, boolean ignoringAnnotations) {
if (a.getRange().isPresent() && !b.getRange().isPresent()) {
if (a.hasRange() && !b.hasRange()) {
return -1;
}
if (!a.getRange().isPresent() && b.getRange().isPresent()) {
if (!a.hasRange() && b.hasRange()) {
return 1;
}
if (!a.getRange().isPresent() && !b.getRange().isPresent()) {
if (!a.hasRange() && !b.hasRange()) {
return 0;
}
if (ignoringAnnotations) {
Expand Down Expand Up @@ -122,7 +122,7 @@ private static Node firstNonAnnotationNode(Node node) {
ClassOrInterfaceDeclaration casted = (ClassOrInterfaceDeclaration) node;
Modifier earliestModifier = casted.getModifiers()
.stream()
.filter(modifier -> modifier.getRange().isPresent())
.filter(modifier -> modifier.hasRange())
.min(Comparator.comparing(o -> o.getRange().get().begin))
.orElse(null);
if (earliestModifier == null) {
Expand All @@ -135,7 +135,7 @@ private static Node firstNonAnnotationNode(Node node) {
MethodDeclaration casted = (MethodDeclaration) node;
Modifier earliestModifier = casted.getModifiers()
.stream()
.filter(modifier -> modifier.getRange().isPresent())
.filter(modifier -> modifier.hasRange())
.min(Comparator.comparing(o -> o.getRange().get().begin))
.orElse(null);
if (earliestModifier == null) {
Expand All @@ -148,7 +148,7 @@ private static Node firstNonAnnotationNode(Node node) {
FieldDeclaration casted = (FieldDeclaration) node;
Modifier earliestModifier = casted.getModifiers()
.stream()
.filter(modifier -> modifier.getRange().isPresent())
.filter(modifier -> modifier.hasRange())
.min(Comparator.comparing(o -> o.getRange().get().begin))
.orElse(null);
if (earliestModifier == null) {
Expand All @@ -173,10 +173,10 @@ private static Node firstNonAnnotationNode(Node node) {
* `container == other`, the raw `other` may extend beyond the sans-annotations `container` thus return false.
*/
public static boolean nodeContains(Node container, Node other, boolean ignoringAnnotations) {
if (!container.getRange().isPresent()) {
if (!container.hasRange()) {
throw new IllegalArgumentException("Cannot compare the positions of nodes if container node does not have a range.");
}
if (!other.getRange().isPresent()) {
if (!other.hasRange()) {
throw new IllegalArgumentException("Cannot compare the positions of nodes if contained node does not have a range.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,22 @@ private SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String n
ListIterator<Statement> statementListIterator = nodeWithStmt.getStatements().listIterator(position);
while(statementListIterator.hasPrevious()) {
Context prevContext = JavaParserFactory.getContext(statementListIterator.previous(), typeSolver);
if (prevContext instanceof BlockStmtContext) {
// Issue #3631
// We have an explicit check for "BlockStmtContext" to avoid resolving the variable x with the
// declaration defined in the block preceding the use of the variable
// For example consider the following:
//
// int x = 0;
// void method() {
// {
// var x = 1;
// System.out.println(x); // prints 1
// }
// System.out.println(x); // prints 0
// }
continue;
}
if (prevContext instanceof StatementContext) {
// We have an explicit check for "StatementContext" to prevent a factorial increase of visited statements.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public ResolvedType transformTypeParameters(ResolvedTypeTransformer transformer)
}

public List<ResolvedReferenceType> getAllAncestors() {
// We need to go through the inheritance line and propagate the type parametes
// We need to go through the inheritance line and propagate the type parameters

List<ResolvedReferenceType> ancestors = typeDeclaration.getAllAncestors();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,27 @@

package com.github.javaparser.symbolsolver.javaparsermodel.declarations;

import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.Test;

import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.ast.expr.VariableDeclarationExpr;
import com.github.javaparser.resolution.declarations.AssociableToAST;
import com.github.javaparser.resolution.declarations.AssociableToASTTest;
import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
import com.github.javaparser.resolution.declarations.ResolvedValueDeclarationTest;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;

import java.util.Optional;

class JavaParserVariableDeclarationTest implements ResolvedValueDeclarationTest,
AssociableToASTTest<VariableDeclarationExpr> {

Expand All @@ -56,5 +65,36 @@ public JavaParserVariableDeclaration createValue() {
public String getCanonicalNameOfExpectedType(ResolvedValueDeclaration resolvedDeclaration) {
return String.class.getCanonicalName();
}

@Test
void test3631() {
String code = ""
+ "class InnerScope {\n"
+ " int x = 0;\n"
+ " void method() {\n"
+ " {\n"
+ " var x = 1;\n"
+ " System.out.println(x); // prints 1\n"
+ " }\n"
+ " System.out.println(x); // prints 0\n"
+ " }\n"
+ " public static void main(String[] args) {\n"
+ " new InnerScope().method();\n"
+ " }\n"
+ "}";

ParserConfiguration configuration = new ParserConfiguration()
.setSymbolResolver(new JavaSymbolSolver(new CombinedTypeSolver(new ReflectionTypeSolver())));
StaticJavaParser.setConfiguration(configuration);

CompilationUnit cu = StaticJavaParser.parse(code);

List<NameExpr> names = cu.findAll(NameExpr.class);
ResolvedValueDeclaration rvd = names.get(3).resolve();

String decl = rvd.asField().toAst().get().toString();

assertTrue("int x = 0;".equals(decl));
}

}