From 21e055c2943103491a95090b5e2354c4b78314aa Mon Sep 17 00:00:00 2001 From: Noah Santschi-Cooney Date: Mon, 19 Apr 2021 15:02:32 +0100 Subject: [PATCH 1/2] fix range building for tabs or mixed tabs/spaces files --- .../semanticdb_javac/SemanticdbVisitor.java | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java index ba7b5d5a..89ea09fa 100644 --- a/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java +++ b/semanticdb-javac/src/main/java/com/sourcegraph/semanticdb_javac/SemanticdbVisitor.java @@ -255,6 +255,7 @@ private String semanticdbSymbol(Symbol sym) { private Optional semanticdbRange( JCDiagnostic.DiagnosticPosition pos, CompilerRange kind, Symbol sym) { + LineMap lineMap = event.getCompilationUnit().getLineMap(); if (sym == null) return Optional.empty(); int start, end; if (kind.isFromPoint() && sym.name != null) { @@ -269,10 +270,17 @@ private Optional semanticdbRange( } if (kind.isFromTextSearch() && sym.name.length() > 0) { - return RangeFinder.findRange( - getCurrentPath(), trees, getCurrentPath().getCompilationUnit(), sym, start, this.source); + Optional range = + RangeFinder.findRange( + getCurrentPath(), + trees, + getCurrentPath().getCompilationUnit(), + sym, + start, + this.source); + if (range.isPresent()) return Optional.of(correctForTabs(range.get(), lineMap, start)); + else return range; } else if (start != Position.NOPOS && end != Position.NOPOS && end > start) { - LineMap lineMap = event.getCompilationUnit().getLineMap(); Semanticdb.Range range = Semanticdb.Range.newBuilder() .setStartLine((int) lineMap.getLineNumber(start) - 1) @@ -280,10 +288,35 @@ private Optional semanticdbRange( .setEndLine((int) lineMap.getLineNumber(end) - 1) .setEndCharacter((int) lineMap.getColumnNumber(end) - 1) .build(); + + range = correctForTabs(range, lineMap, start); + return Optional.of(range); - } else { - return Optional.empty(); } + + return Optional.empty(); + } + + private Semanticdb.Range correctForTabs(Semanticdb.Range range, LineMap lineMap, int start) { + int startLinePos = (int) lineMap.getPosition(lineMap.getLineNumber(start), 0); + + // javac replaces every tab with 8 spaces in the linemap. As this is potentially inconsistent + // with the source file itself, we adjust for that here if the line is actually indented with + // tabs. + // As for every tab there are 8 spaces, we remove 7 spaces for every tab to get the correct + // char offset (note: different to _column_ offset your editor shows) + if (this.source.charAt(startLinePos) == '\t') { + int count = 1; + while (this.source.charAt(++startLinePos) == '\t') count++; + range = + range + .toBuilder() + .setStartCharacter(range.getStartCharacter() - (count * 7)) + .setEndCharacter(range.getEndCharacter() - (count * 7)) + .build(); + } + + return range; } private Optional semanticdbOccurrence( From 02a224324f888b29284885a133adc23517e296b3 Mon Sep 17 00:00:00 2001 From: Noah Santschi-Cooney Date: Tue, 20 Apr 2021 13:42:49 +0100 Subject: [PATCH 2/2] add snapshot source for tab indented file --- build.sbt | 3 ++ .../src/main/java/minimized/TabIndented.java | 17 +++++++++++ .../main/generated/minimized/TabIndented.java | 30 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 tests/minimized/src/main/java/minimized/TabIndented.java create mode 100644 tests/snapshots/src/main/generated/minimized/TabIndented.java diff --git a/build.sbt b/build.sbt index 3a6001cb..2a7da805 100644 --- a/build.sbt +++ b/build.sbt @@ -230,16 +230,19 @@ lazy val minimized = project .in(file("tests/minimized/.j11")) .settings(minimizedSettings) .dependsOn(agent, plugin) + .disablePlugins(JavaFormatterPlugin) lazy val minimized8 = project .in(file("tests/minimized/.j8")) .settings(minimizedSettings, javaToolchainVersion := "8") .dependsOn(agent, plugin) + .disablePlugins(JavaFormatterPlugin) lazy val minimized15 = project .in(file("tests/minimized/.j15")) .settings(minimizedSettings, javaToolchainVersion := "15") .dependsOn(agent, plugin) + .disablePlugins(JavaFormatterPlugin) lazy val minimizedScala = project .in(file("tests/minimized-scala")) diff --git a/tests/minimized/src/main/java/minimized/TabIndented.java b/tests/minimized/src/main/java/minimized/TabIndented.java new file mode 100644 index 00000000..e53e569c --- /dev/null +++ b/tests/minimized/src/main/java/minimized/TabIndented.java @@ -0,0 +1,17 @@ +package minimized; + +public class TabIndented { + public void app() { + Object o = new Object() { + @Override + public boolean equals(Object other) { + return false; + } + + @Override + public String toString() { + return ""; + } + }; + } +} diff --git a/tests/snapshots/src/main/generated/minimized/TabIndented.java b/tests/snapshots/src/main/generated/minimized/TabIndented.java new file mode 100644 index 00000000..447c4ae1 --- /dev/null +++ b/tests/snapshots/src/main/generated/minimized/TabIndented.java @@ -0,0 +1,30 @@ +package minimized; + +public class TabIndented { +// ^^^^^^^^^^^ definition minimized/TabIndented# public class TabIndented +// ^^^^^^^^^^^ definition minimized/TabIndented#``(). public TabIndented() +→public void app() { +// ^^^ definition minimized/TabIndented#app(). public void app() +→→Object o = new Object() { +//^^^^^^ reference java/lang/Object# +// ^ definition local0 Object o +// ^^^^^^ reference java/lang/Object# +→→→@Override +// ^^^^^^^^ reference java/lang/Override# +→→→public boolean equals(Object other) { +// ^^^^^^ definition local3 @Override public boolean equals(Object other) +// ^^^^^^ reference java/lang/Object# +// ^^^^^ definition local5 Object other +→→→→return false; +→→→} + +→→→@Override +// ^^^^^^^^ reference java/lang/Override# +→→→public String toString() { +// ^^^^^^ reference java/lang/String# +// ^^^^^^^^ definition local4 @Override public String toString() +→→→→return ""; +→→→} +→→}; +→} +}