Skip to content

Commit c6e8498

Browse files
committed
Made the marker locator more precise.
Instead of the using the narrow piece of code reported in the error messages of the type checker, I used the enclosing line of the reported piece of code to locate the marker in the primary project more precisely. The enclosing line results in more precise marker location because it's longer and is more likely to be unique in the enclosing compilation unit. issue #62
1 parent 92fc4e4 commit c6e8498

File tree

14 files changed

+269
-126
lines changed

14 files changed

+269
-126
lines changed

plugins/checker.framework.change.propagator/.classpath

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
44
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
55
<classpathentry kind="src" path="src"/>
6+
<classpathentry kind="src" path="test"/>
67
<classpathentry kind="output" path="bin"/>
78
</classpath>

plugins/checker.framework.change.propagator/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Require-Bundle: org.eclipse.core.runtime,
1717
org.eclipse.core.filebuffers,
1818
org.eclipse.text,
1919
com.google.guava,
20-
org.apache.commons.lang3
20+
org.apache.commons.lang3,
21+
org.junit
2122
Bundle-ActivationPolicy: lazy
2223
Export-Package: checker.framework.change.propagator

plugins/checker.framework.change.propagator/src/checker/framework/change/propagator/MarkerLocationDescriptor.java

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,59 @@ public class MarkerLocationDescriptor {
66

77
private final CompilationUnitDescriptor compilationUnitDescriptor;
88

9-
private final int initialOffset;
9+
private final int codeSnippetOffsetRelativeToSurroundingCodeSnippet;
1010

11-
private final int initialLength;
11+
private final int codeSnippetLength;
1212

1313
private final String codeSnippet;
1414

15+
private final int surroundingCodeSnippetOffset;
16+
17+
private final int surroundingCodeSnippetLength;
18+
19+
private final String surroundingCodeSnippet;
20+
1521
public MarkerLocationDescriptor(
1622
CompilationUnitDescriptor compilationUnitDescriptor,
17-
int initialOffset, int initialLength, String codeSnippet) {
23+
int codeSnippetOffsetRelativeToSurroundingCodeSnippet,
24+
int codeSnippetLength, String codeSnippet,
25+
String surroundingCodeSnippet, int surroundingCodeSnippetOffset,
26+
int surroundingCodeSnippetLength) {
1827
this.compilationUnitDescriptor = compilationUnitDescriptor;
19-
this.initialOffset = initialOffset;
20-
this.initialLength = initialLength;
28+
this.codeSnippetOffsetRelativeToSurroundingCodeSnippet = codeSnippetOffsetRelativeToSurroundingCodeSnippet;
29+
this.codeSnippetLength = codeSnippetLength;
2130
this.codeSnippet = codeSnippet;
31+
this.surroundingCodeSnippet = surroundingCodeSnippet;
32+
this.surroundingCodeSnippetOffset = surroundingCodeSnippetOffset;
33+
this.surroundingCodeSnippetLength = surroundingCodeSnippetLength;
2234
}
2335

2436
CompilationUnitDescriptor getCompilationUnitDescriptor() {
2537
return compilationUnitDescriptor;
2638
}
2739

28-
int getInitialOffset() {
29-
return initialOffset;
40+
int getCodeSnippetOffsetRelativeToSurroundingCodeSnippet() {
41+
return codeSnippetOffsetRelativeToSurroundingCodeSnippet;
42+
}
43+
44+
int getCodeSnippetLength() {
45+
return codeSnippetLength;
3046
}
3147

32-
int getInitialLength() {
33-
return initialLength;
48+
int getSurroundingCodeSnippetOffset() {
49+
return surroundingCodeSnippetOffset;
50+
}
51+
52+
int getSurroundingCodeSnippetLength() {
53+
return surroundingCodeSnippetLength;
3454
}
3555

3656
String getCodeSnippet() {
3757
return codeSnippet;
3858
}
3959

60+
String getSurroundingCodeSnippet() {
61+
return surroundingCodeSnippet;
62+
}
63+
4064
}

plugins/checker.framework.change.propagator/src/checker/framework/change/propagator/MarkerLocationDescriptorFactory.java

Lines changed: 46 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -11,67 +11,50 @@
1111

1212
public class MarkerLocationDescriptorFactory {
1313

14-
private final IMarker marker;
15-
16-
private final CompilationUnitDescriptorFactory compilationUnitDescriptorFactory = new CompilationUnitDescriptorFactory();
17-
18-
public MarkerLocationDescriptorFactory(IMarker marker) {
19-
this.marker = marker;
20-
}
21-
22-
// Adapted from
23-
// http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Fporting%2F3.3%2Frecommended.html
24-
private ICompilationUnit toCompilationUnit(IResource resource) {
25-
return (ICompilationUnit) JavaCore.create(resource);
26-
}
27-
28-
public MarkerLocationDescriptor get() {
29-
ICompilationUnit compilationUnit = toCompilationUnit(marker
30-
.getResource());
31-
CompilationUnitDescriptor compilationUnitDescriptor = compilationUnitDescriptorFactory
32-
.get(compilationUnit);
33-
String text = new CompilationUnitTextExtractor(compilationUnit)
34-
.getText();
35-
try {
36-
Integer beginIndex = (Integer) marker
37-
.getAttribute(IMarker.CHAR_START);
38-
Integer endIndex = (Integer) marker.getAttribute(IMarker.CHAR_END);
39-
if (beginIndex < 0) {
40-
beginIndex = 0;
41-
}
42-
if (endIndex < beginIndex) {
43-
endIndex = beginIndex;
44-
}
45-
return new MarkerLocationDescriptor(compilationUnitDescriptor,
46-
beginIndex, endIndex - beginIndex, enclosingLine(text,
47-
beginIndex, endIndex));
48-
} catch (CoreException e) {
49-
throw new RuntimeException(e);
50-
}
51-
}
52-
53-
/**
54-
*
55-
* @param text
56-
* @param beginIndex
57-
* @param endIndex
58-
* @return the largest substring of text that contains [beginIndex,
59-
* endIndex) and doesn't include any new line characters.
60-
*/
61-
private String enclosingLine(String text, int beginIndex, int endIndex) {
62-
String separator = System.getProperty("line.separator");
63-
int indexOfNextSeparator = text.indexOf(separator, endIndex);
64-
if (indexOfNextSeparator == -1) {
65-
indexOfNextSeparator = endIndex;
66-
}
67-
int indexOfPreviousSeparator = text.substring(0, beginIndex - 1)
68-
.lastIndexOf(separator);
69-
if (indexOfPreviousSeparator == -1) {
70-
indexOfPreviousSeparator = beginIndex;
71-
} else {
72-
++indexOfPreviousSeparator;
73-
}
74-
return text.substring(indexOfPreviousSeparator, indexOfNextSeparator);
75-
}
76-
14+
private final IMarker marker;
15+
16+
private final CompilationUnitDescriptorFactory compilationUnitDescriptorFactory = new CompilationUnitDescriptorFactory();
17+
18+
public MarkerLocationDescriptorFactory(IMarker marker) {
19+
this.marker = marker;
20+
}
21+
22+
// Adapted from
23+
// http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Fporting%2F3.3%2Frecommended.html
24+
private ICompilationUnit toCompilationUnit(IResource resource) {
25+
return (ICompilationUnit) JavaCore.create(resource);
26+
}
27+
28+
public MarkerLocationDescriptor get() {
29+
ICompilationUnit compilationUnit = toCompilationUnit(marker
30+
.getResource());
31+
CompilationUnitDescriptor compilationUnitDescriptor = compilationUnitDescriptorFactory
32+
.get(compilationUnit);
33+
String text = new CompilationUnitTextExtractor(compilationUnit)
34+
.getText();
35+
try {
36+
Integer beginIndex = (Integer) marker
37+
.getAttribute(IMarker.CHAR_START);
38+
Integer endIndex = (Integer) marker.getAttribute(IMarker.CHAR_END);
39+
if (beginIndex < 0) {
40+
beginIndex = 0;
41+
}
42+
if (endIndex < beginIndex) {
43+
endIndex = beginIndex;
44+
}
45+
Substring codeSnippet = Substring.indexBasedSubstring(text,
46+
beginIndex, endIndex);
47+
Substring surroundingCodeSnippet = StringUtils
48+
.enclosingLine(codeSnippet);
49+
return new MarkerLocationDescriptor(compilationUnitDescriptor,
50+
codeSnippet.getBeginIndex()
51+
- surroundingCodeSnippet.getBeginIndex(),
52+
codeSnippet.getLength(), codeSnippet.toString(),
53+
surroundingCodeSnippet.toString(),
54+
surroundingCodeSnippet.getBeginIndex(),
55+
surroundingCodeSnippet.getLength());
56+
} catch (CoreException e) {
57+
throw new RuntimeException(e);
58+
}
59+
}
7760
}

plugins/checker.framework.change.propagator/src/checker/framework/change/propagator/MarkerLocationFactory.java

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,46 +15,52 @@
1515

1616
public class MarkerLocationFactory {
1717

18-
private final MarkerLocationDescriptor markerLocationDescriptor;
19-
20-
public MarkerLocationFactory(MarkerLocationDescriptor markerDescriptor) {
21-
this.markerLocationDescriptor = markerDescriptor;
22-
}
23-
24-
public Optional<MarkerLocation> createMarkerLocation(
25-
IJavaProject javaProject) {
26-
CompilationUnitFactory compilationUnitFactory = new CompilationUnitFactory(
27-
javaProject,
28-
markerLocationDescriptor.getCompilationUnitDescriptor());
29-
ICompilationUnit compilationUnit = compilationUnitFactory
30-
.getJavaElement();
31-
CompilationUnitTextExtractor textExtractor = new CompilationUnitTextExtractor(
32-
compilationUnit);
33-
return findBestMatch(compilationUnit, textExtractor.getText());
34-
}
35-
36-
private Optional<MarkerLocation> findBestMatch(
37-
ICompilationUnit compilationUnit, String text) {
38-
Set<MarkerLocation> matches = new HashSet<>();
39-
Pattern p = Pattern.compile(Pattern.quote(markerLocationDescriptor
40-
.getCodeSnippet()));
41-
Matcher m = p.matcher(text);
42-
while (m.find()) {
43-
matches.add(new MarkerLocation(compilationUnit, m.start(), m.end()
44-
- m.start()));
45-
}
46-
if (matches.isEmpty()) {
47-
return Optional.absent();
48-
}
49-
MarkerLocation bestMatch = Ordering
50-
.natural()
51-
.onResultOf(
52-
(MarkerLocation markerLocation) -> Math
53-
.abs(markerLocationDescriptor
54-
.getInitialOffset()
55-
- markerLocation.getOffset()))
56-
.min(matches);
57-
return Optional.of(bestMatch);
58-
}
18+
private final MarkerLocationDescriptor markerLocationDescriptor;
19+
20+
public MarkerLocationFactory(MarkerLocationDescriptor markerDescriptor) {
21+
this.markerLocationDescriptor = markerDescriptor;
22+
}
23+
24+
public Optional<MarkerLocation> createMarkerLocation(
25+
IJavaProject javaProject) {
26+
CompilationUnitFactory compilationUnitFactory = new CompilationUnitFactory(
27+
javaProject,
28+
markerLocationDescriptor.getCompilationUnitDescriptor());
29+
ICompilationUnit compilationUnit = compilationUnitFactory
30+
.getJavaElement();
31+
CompilationUnitTextExtractor cuTextExtractor = new CompilationUnitTextExtractor(
32+
compilationUnit);
33+
return findBestMatch(compilationUnit, cuTextExtractor.getText());
34+
}
35+
36+
private Optional<MarkerLocation> findBestMatch(
37+
ICompilationUnit compilationUnit, String text) {
38+
Set<MarkerLocation> matches = new HashSet<>();
39+
Pattern p = Pattern.compile(Pattern.quote(markerLocationDescriptor
40+
.getSurroundingCodeSnippet()));
41+
Matcher m = p.matcher(text);
42+
while (m.find()) {
43+
matches.add(new MarkerLocation(compilationUnit, m.start(), m.end()
44+
- m.start()));
45+
}
46+
if (matches.isEmpty()) {
47+
return Optional.absent();
48+
}
49+
MarkerLocation bestMatch = Ordering
50+
.natural()
51+
.onResultOf(
52+
(MarkerLocation markerLocation) -> Math
53+
.abs(markerLocationDescriptor
54+
.getSurroundingCodeSnippetOffset()
55+
- markerLocation.getOffset()))
56+
.min(matches);
57+
return Optional
58+
.of(new MarkerLocation(
59+
compilationUnit,
60+
bestMatch.getOffset()
61+
+ markerLocationDescriptor
62+
.getCodeSnippetOffsetRelativeToSurroundingCodeSnippet(),
63+
markerLocationDescriptor.getCodeSnippetLength()));
64+
}
5965

6066
}

plugins/checker.framework.change.propagator/src/checker/framework/change/propagator/ResolutionHelper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package checker.framework.change.propagator;
22

3+
import static com.google.common.collect.Iterables.getFirst;
4+
35
import java.util.HashSet;
46
import java.util.Set;
57

@@ -14,8 +16,6 @@
1416
import com.google.common.collect.HashMultimap;
1517
import com.google.common.collect.SetMultimap;
1618

17-
import static com.google.common.collect.Iterables.getFirst;
18-
1919
public class ResolutionHelper {
2020
private static final CheckerResolutionGenerator checkerResolutionGenerator = new CheckerResolutionGenerator();
2121

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package checker.framework.change.propagator;
2+
3+
public class StringUtils {
4+
5+
/**
6+
*
7+
* @param text
8+
* @param beginIndex
9+
* @param endIndex
10+
* @return the largest substring of text that contains [beginIndex,
11+
* endIndex) and doesn't include any new line characters.
12+
*/
13+
static Substring enclosingLine(Substring substring) {
14+
String separator = System.getProperty("line.separator");
15+
String adjustedText = '\n' + substring.getEnclosingString() + '\n';
16+
int adjustedBeginIndex = substring.getBeginIndex() + 1;
17+
int adjustedEndIndex = substring.getEndIndex() + 1;
18+
int indexOfPreviousSeparator = adjustedText.substring(0,
19+
adjustedBeginIndex).lastIndexOf(separator);
20+
int indexOfNextSeparator = adjustedText.indexOf(separator,
21+
adjustedEndIndex);
22+
return Substring.indexBasedSubstring(substring.getEnclosingString(),
23+
indexOfPreviousSeparator, indexOfNextSeparator - 1);
24+
}
25+
26+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package checker.framework.change.propagator;
2+
3+
/**
4+
* Represents the substring [beginIndex, endIndex) of string.
5+
*
6+
*/
7+
public class Substring {
8+
9+
private final String enclosingString;
10+
11+
private final int beginIndex;
12+
13+
private final int endIndex;
14+
15+
private Substring(String string, int beginIndex, int endIndex) {
16+
this.enclosingString = string;
17+
this.beginIndex = beginIndex;
18+
this.endIndex = endIndex;
19+
}
20+
21+
public static Substring indexBasedSubstring(String string, int beginIndex,
22+
int endIndex) {
23+
return new Substring(string, beginIndex, endIndex);
24+
}
25+
26+
public String getEnclosingString() {
27+
return enclosingString;
28+
}
29+
30+
public int getBeginIndex() {
31+
return beginIndex;
32+
}
33+
34+
public int getEndIndex() {
35+
return endIndex;
36+
}
37+
38+
public int getLength() {
39+
return endIndex - beginIndex;
40+
}
41+
42+
@Override
43+
public String toString() {
44+
return enclosingString.substring(beginIndex, endIndex);
45+
}
46+
47+
}

0 commit comments

Comments
 (0)