Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Next Release (Version 3.15.23)
(PR [#2679](https://github.com/javaparser/javaparser/pull/2679), by [@MysterAitch](https://github.com/MysterAitch))
* BREAKING CHANGE: Tokens relating to literal values now have the category of `JavaToken.Category.LITERAL` (previously `JavaToken.Category.KEYWORD`)
(PR [#2679](https://github.com/javaparser/javaparser/pull/2679), by [@MysterAitch](https://github.com/MysterAitch))
* FIXED: Add symbol solver support for variadic parameters given zero or more than one argument, and when an array is given
(PR [#2675](https://github.com/javaparser/javaparser/pull/2675), by [@hfreeb](https://github.com/hfreeb))



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.jbehave.core.annotations.Then;
import org.jbehave.core.annotations.When;

import static com.github.javaparser.Position.pos;
import static com.github.javaparser.Range.range;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand All @@ -48,12 +47,12 @@ public void reset() {
secondRange = null;
}
/*
* Given steps
* Given steps
*/

@Given("the position $line, $column")
public void givenThePosition(int line, int column) {
this.position = pos(line, column);
this.position = new Position(line, column);
}

@Given("the range $line1, $column1 - $line2, $column2")
Expand All @@ -62,12 +61,12 @@ public void givenTheRange(int line1, int column1, int line2, int column2) {
}

/*
* When steps
* When steps
*/

@When("I compare to position $line, $column")
public void iCompareToPosition(int line, int column) {
secondPosition = pos(line, column);
secondPosition = new Position(line, column);
}

@When("I compare to range $line1, $column1 - $line2, $column2")
Expand All @@ -76,7 +75,7 @@ public void whenICompareToRange(int line1, int column1, int line2, int column2)
}

/*
* Then steps
* Then steps
*/

@Then("the positions are equal")
Expand Down
129 changes: 93 additions & 36 deletions javaparser-core/src/main/java/com/github/javaparser/Position.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

import com.github.javaparser.ast.Node;

import java.util.Objects;

import static com.github.javaparser.utils.Utils.assertNotNull;

/**
Expand All @@ -33,15 +35,41 @@ public class Position implements Comparable<Position> {
public final int column;

/**
* The first position in the file
* The first line -- note that it is 1-indexed (i.e. the first line is line 1, as opposed to 0)
*/
public static final int FIRST_LINE = 1;
/**
* The first column -- note that it is 1-indexed (i.e. the first column is column 1, as opposed to 0)
*/
public static final Position HOME = new Position(1, 1);
public static final int FIRST_COLUMN = 1;
/**
* The first position in the file.
*/
public static final Position HOME = new Position(FIRST_LINE, FIRST_COLUMN);


/**
* Line numbers must be positive, thus
*/
public static final int ABSOLUTE_BEGIN_LINE = -1;

public static final int ABSOLUTE_END_LINE = -2;


/**
* TODO: Do we refer to the characters as columns,
* ...or the spaces between (thus also before/after) characters as columns?
*/
public Position(int line, int column) {
if (line < Node.ABSOLUTE_END_LINE) {
if (line < Position.ABSOLUTE_END_LINE) {
// TODO/FIXME: This doesn't read correctly due to use of the variable.
throw new IllegalArgumentException("Can't position at line " + line);
}
if (column < -1) {
// TODO: This allows/permits column 0, which seemingly contradicts first column being 1
// ... (see also nextLine() which indicates 1 being the first column of the next line)
// ... (see also valid() which requires a column > 0)
// TODO: Maybe we need an "ABSOLUTE_BEGIN_LINE" and "ABSOLUTE_END_LINE"?
throw new IllegalArgumentException("Can't position at column " + column);
}
this.line = line;
Expand All @@ -50,15 +78,24 @@ public Position(int line, int column) {

/**
* Convenient factory method.
*
* @deprecated Use the constructor (e.g. {@code new Position(line, column)})
*/
@Deprecated
public static Position pos(int line, int column) {
return new Position(line, column);
}

/**
* @return Jump to the given column number, while retaining the current line number.
*/
public Position withColumn(int column) {
return new Position(this.line, column);
}

/**
* @return Jump to the given line number, while retaining the current column number.
*/
public Position withLine(int line) {
return new Position(line, this.column);
}
Expand All @@ -74,69 +111,88 @@ public Position right(int characters) {
* @return a position that is on the start of the next line from this position.
*/
public Position nextLine() {
return new Position(line + 1, HOME.column);
return new Position(line + 1, FIRST_COLUMN);
}

/**
* Check if the position is usable. Does not know what it is pointing at, so it can't check if the position is after
* the end of the source.
* Check if the position is usable.
* Does not know what it is pointing at, so it can't check if the position is after the end of the source.
*/
public boolean valid() {
return line > 0 && column > 0;
// TODO / FIXME: Perhaps allow use of the "special" positions e.g. ABSOLUTE_BEGIN_LINE and ABSOLUTE_END_LINE...?
return line >= FIRST_LINE && column >= FIRST_COLUMN;
}

/**
* @see #valid()
* @return The inverse of {@link #valid()}
*/
public boolean invalid() {
return !valid();
}

public Position orIfInvalid(Position anotherPosition) {
assertNotNull(anotherPosition);
if (valid() || anotherPosition.invalid()) {
/**
* @return If this position is valid, this.
* Otherwise, if the alternativePosition is valid, return that.
* Otherwise otherwise, just return this.
* TODO: Simplify/clarify.
*/
public Position orIfInvalid(Position alternativePosition) {
assertNotNull(alternativePosition);
// TODO: Why the || ?
// ... It seems that if both this and the alternative are invalid, then we return this..?
if (valid() || alternativePosition.invalid()) {
return this;
}
return anotherPosition;
return alternativePosition;
}

public boolean isAfter(Position position) {
assertNotNull(position);
if (position.line == Node.ABSOLUTE_BEGIN_LINE) return true;
if (line > position.line) {
public boolean isAfter(Position otherPosition) {
assertNotNull(otherPosition);
if (otherPosition.line == Position.ABSOLUTE_BEGIN_LINE) {
// FIXME: What if both positions are on the same line but different columns..?
return true;
}
if (line > otherPosition.line) {
return true;
} else if (line == position.line) {
return column > position.column;
} else if (line == otherPosition.line) {
return column > otherPosition.column;
}
return false;

}

public boolean isAfterOrEqual(Position position) {
assertNotNull(position);
return isAfter(position) || equals(position);
public boolean isAfterOrEqual(Position otherPosition) {
assertNotNull(otherPosition);
return isAfter(otherPosition) || equals(otherPosition);
}

public boolean isBefore(Position position) {
assertNotNull(position);
if (position.line == Node.ABSOLUTE_END_LINE) return true;
if (line < position.line) {
public boolean isBefore(Position otherPosition) {
assertNotNull(otherPosition);
if (otherPosition.line == Position.ABSOLUTE_END_LINE) {
// FIXME: What if both positions are on the same line but different columns..?
return true;
}
if (line < otherPosition.line) {
return true;
} else if (line == position.line) {
return column < position.column;
} else if (line == otherPosition.line) {
return column < otherPosition.column;
}
return false;
}

public boolean isBeforeOrEqual(Position position) {
assertNotNull(position);
return isBefore(position) || equals(position);
public boolean isBeforeOrEqual(Position otherPosition) {
assertNotNull(otherPosition);
return isBefore(otherPosition) || equals(otherPosition);
}

@Override
public int compareTo(Position o) {
assertNotNull(o);
if (isBefore(o)) {
public int compareTo(Position otherPosition) {
assertNotNull(otherPosition);
if (isBefore(otherPosition)) {
return -1;
}
if (isAfter(o)) {
if (isAfter(otherPosition)) {
return 1;
}
return 0;
Expand All @@ -147,14 +203,15 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Position position = (Position) o;
Position otherPosition = (Position) o;

return line == position.line && column == position.column;
return Objects.equals(line, otherPosition.line)
&& Objects.equals(column, otherPosition.column);
}

@Override
public int hashCode() {
return 31 * line + column;
return Objects.hash(line, column);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public static Range range(Position begin, Position end) {
* @return A new `Range` object with the given start/end position.
*/
public static Range range(int beginLine, int beginColumn, int endLine, int endColumn) {
return new Range(pos(beginLine, beginColumn), pos(endLine, endColumn));
return new Range(new Position(beginLine, beginColumn), new Position(endLine, endColumn));
}

/**
Expand Down
14 changes: 12 additions & 2 deletions javaparser-core/src/main/java/com/github/javaparser/ast/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package com.github.javaparser.ast;

import com.github.javaparser.HasParentNode;
import com.github.javaparser.Position;
import com.github.javaparser.Range;
import com.github.javaparser.TokenRange;
import com.github.javaparser.ast.comments.BlockComment;
Expand Down Expand Up @@ -401,9 +402,18 @@ protected void setAsParentNodeOf(Node childNode) {
}
}

public static final int ABSOLUTE_BEGIN_LINE = -1;
/**
* @deprecated Use {@link Position#ABSOLUTE_BEGIN_LINE}
*/
@Deprecated
public static final int ABSOLUTE_BEGIN_LINE = Position.ABSOLUTE_BEGIN_LINE;


public static final int ABSOLUTE_END_LINE = -2;
/**
* @deprecated Use {@link Position#ABSOLUTE_END_LINE}
*/
@Deprecated
public static final int ABSOLUTE_END_LINE = Position.ABSOLUTE_END_LINE;

public void tryAddImportToParentCompilationUnit(Class<?> clazz) {
findAncestor(CompilationUnit.class).ifPresent(p -> p.addImport(clazz));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
import java.util.Deque;
import java.util.LinkedList;

import static com.github.javaparser.Position.*;

/**
* A support class for code that outputs formatted source code.
*/
Expand All @@ -43,7 +41,7 @@ public class SourcePrinter {
private final Deque<String> reindentedIndents = new LinkedList<>();
private String lastPrintedIndent = "";
private final StringBuilder buf = new StringBuilder();
private Position cursor = new Position(1, 0);
private Position cursor = new Position(Position.FIRST_LINE, Position.FIRST_COLUMN - 1); // Start before the first column
private boolean indented = false;

SourcePrinter() {
Expand Down Expand Up @@ -198,7 +196,7 @@ public SourcePrinter println(final String arg) {
*/
public SourcePrinter println() {
buf.append(endOfLineCharacter);
cursor = pos(cursor.line + 1, 0);
cursor = new Position(cursor.line + 1, Position.FIRST_COLUMN - 1); // Start before the first column
indented = false;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ public MethodUsage resolveTypeVariables(Context context, List<ResolvedType> para
for (int i = 0; i < methodDeclaration.getNumberOfParams(); i++) {
ResolvedParameterDeclaration formalParamDecl = methodDeclaration.getParam(i);
ResolvedType formalParamType = formalParamDecl.getType();

// Don't continue if a vararg parameter is reached and there are no arguments left
if (formalParamDecl.isVariadic() && parameterTypes.size() < methodDeclaration.getNumberOfParams()) {
break;
}

ResolvedType actualParamType = parameterTypes.get(i);

if (formalParamDecl.isVariadic() && !actualParamType.isArray()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,15 @@ private ResolvedTypeDeclaration checkAncestorsForType(String name, ResolvedRefer
}

public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> argumentsTypes, boolean staticOnly) {

// Begin by locating methods declared "here"
List<ResolvedMethodDeclaration> candidateMethods = typeDeclaration.getDeclaredMethods().stream()
.filter(m -> m.getName().equals(name))
.filter(m -> !staticOnly || m.isStatic())
.collect(Collectors.toList());
// We want to avoid infinite recursion in case of Object having Object as ancestor

// Next, consider methods declared within ancestors.
// Note that we only consider ancestors when we are not currently at java.lang.Object (avoiding infinite recursion).
if (!Object.class.getCanonicalName().equals(typeDeclaration.getQualifiedName())) {
for (ResolvedReferenceType ancestor : typeDeclaration.getAncestors(true)) {
// Avoid recursion on self
Expand All @@ -144,8 +148,8 @@ public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<
.stream()
.filter(m -> m.getName().equals(name))
.collect(Collectors.toList()));
SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic
.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly);
SymbolReference<ResolvedMethodDeclaration> res = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, staticOnly);

// consider methods from superclasses and only default methods from interfaces :
// not true, we should keep abstract as a valid candidate
// abstract are removed in MethodResolutionLogic.isApplicable is necessary
Expand All @@ -155,8 +159,10 @@ public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<
}
}
}
// We want to avoid infinite recursion when a class is using its own method
// see issue #75

// If we haven't located any candidates that are declared on this type or its ancestors, consider the parent context.
// This is relevant e.g. with nested classes.
// Note that we want to avoid infinite recursion when a class is using its own method - see issue #75
if (candidateMethods.isEmpty()) {
SymbolReference<ResolvedMethodDeclaration> parentSolution = context.getParent().solveMethod(name, argumentsTypes, staticOnly);
if (parentSolution.isSolved()) {
Expand Down
Loading