Skip to content

Commit 47d85bf

Browse files
committed
trivia index
1 parent 00f0dcf commit 47d85bf

6 files changed

Lines changed: 145 additions & 1 deletion

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/WurstParser.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import de.peeeq.wurstscript.jurst.ExtendedJurstLexer;
1515
import de.peeeq.wurstscript.jurst.antlr.JurstParser;
1616
import de.peeeq.wurstscript.parser.AntlrTokenPipeline;
17+
import de.peeeq.wurstscript.parser.TriviaIndex;
1718
import de.peeeq.wurstscript.parser.WurstAntlrErrorListener;
1819
import de.peeeq.wurstscript.parser.antlr.AntlrWurstParseTreeTransformer;
1920
import de.peeeq.wurstscript.parser.antlr.ExtendedWurstLexer;
@@ -104,6 +105,7 @@ private CompilationUnit parseWithAntlr(Reader reader, final String source, boole
104105
removeSyntacticSugar(root, hasCommonJ);
105106
}
106107
root.getCuInfo().setIndentationMode(lexerRef[0].getIndentationMode());
108+
root.getCuInfo().setTriviaIndex(TriviaIndex.fromTokens(res.tokens.getTokens()));
107109
return root;
108110

109111
} catch (IOException e) {

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/AttrWurstDoc.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
public class AttrWurstDoc {
77

88
public static String getComment(NameDef nameDef) {
9+
String triviaComment = getCommentFromTrivia(nameDef);
10+
if (!triviaComment.isEmpty()) {
11+
return triviaComment;
12+
}
913
if (nameDef instanceof HasModifier) {
1014
HasModifier HasModifier = nameDef;
1115
return getCommmentHelper(HasModifier);
@@ -26,12 +30,28 @@ private static String getCommmentHelper(
2630
}
2731

2832
public static String getComment(ConstructorDef constructorDef) {
33+
String triviaComment = getCommentFromTrivia(constructorDef);
34+
if (!triviaComment.isEmpty()) {
35+
return triviaComment;
36+
}
2937
return getCommmentHelper(constructorDef);
3038
}
3139

3240

41+
private static String getCommentFromTrivia(AstElementWithSource e) {
42+
CompilationUnit cu = e.attrCompilationUnit();
43+
if (cu == null || cu.getCuInfo() == null) {
44+
return "";
45+
}
46+
return cu.getCuInfo().getTriviaIndex().findLeadingHotdoc(e.getSource().getLeftPos());
47+
}
48+
3349
private static String comment(WurstDoc wurstDoc) {
34-
String result = wurstDoc.getRawComment();
50+
return normalizeHotdocComment(wurstDoc.getRawComment());
51+
}
52+
53+
public static String normalizeHotdocComment(String rawComment) {
54+
String result = rawComment;
3555
if (result.length() <= 5) {
3656
return "";
3757
}

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/attributes/CompilationUnitInfo.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package de.peeeq.wurstscript.attributes;
22

3+
import de.peeeq.wurstscript.parser.TriviaIndex;
34
import de.peeeq.wurstscript.utils.Utils;
45

56
/**
@@ -9,6 +10,7 @@ public class CompilationUnitInfo {
910
private String file = "";
1011
private de.peeeq.wurstscript.attributes.ErrorHandler cuErrorHandler;
1112
private IndentationMode indentationMode = IndentationMode.spaces(4);
13+
private TriviaIndex triviaIndex = TriviaIndex.empty();
1214

1315
public CompilationUnitInfo(ErrorHandler cuErrorHandler) {
1416
this.cuErrorHandler = cuErrorHandler;
@@ -38,6 +40,14 @@ public void setIndentationMode(IndentationMode indentationMode) {
3840
this.indentationMode = indentationMode;
3941
}
4042

43+
public TriviaIndex getTriviaIndex() {
44+
return triviaIndex;
45+
}
46+
47+
public void setTriviaIndex(TriviaIndex triviaIndex) {
48+
this.triviaIndex = triviaIndex == null ? TriviaIndex.empty() : triviaIndex;
49+
}
50+
4151
public interface IndentationMode {
4252

4353
static IndentationMode tabs() {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package de.peeeq.wurstscript.parser;
2+
3+
import de.peeeq.wurstscript.antlr.WurstParser;
4+
import de.peeeq.wurstscript.attributes.AttrWurstDoc;
5+
import org.antlr.v4.runtime.Token;
6+
7+
import java.util.ArrayList;
8+
import java.util.Collections;
9+
import java.util.List;
10+
11+
public final class TriviaIndex {
12+
13+
private static final TriviaIndex EMPTY = new TriviaIndex(Collections.emptyList());
14+
15+
private final List<Token> tokens;
16+
17+
private TriviaIndex(List<Token> tokens) {
18+
this.tokens = tokens;
19+
}
20+
21+
public static TriviaIndex empty() {
22+
return EMPTY;
23+
}
24+
25+
public static TriviaIndex fromTokens(List<Token> tokens) {
26+
if (tokens == null || tokens.isEmpty()) {
27+
return EMPTY;
28+
}
29+
return new TriviaIndex(new ArrayList<>(tokens));
30+
}
31+
32+
public String findLeadingHotdoc(int declarationStartOffset) {
33+
int targetTokenIndex = firstNonTriviaTokenAtOrAfter(declarationStartOffset);
34+
if (targetTokenIndex < 0) {
35+
return "";
36+
}
37+
for (int i = targetTokenIndex - 1; i >= 0; i--) {
38+
Token token = tokens.get(i);
39+
int type = token.getType();
40+
if (type == WurstParser.HOTDOC_COMMENT) {
41+
return AttrWurstDoc.normalizeHotdocComment(token.getText());
42+
}
43+
if (!isTriviaBetweenDocAndDeclaration(token)) {
44+
return "";
45+
}
46+
}
47+
return "";
48+
}
49+
50+
private int firstNonTriviaTokenAtOrAfter(int offset) {
51+
for (int i = 0; i < tokens.size(); i++) {
52+
Token token = tokens.get(i);
53+
if (token.getStartIndex() < offset) {
54+
continue;
55+
}
56+
if (!isTriviaBetweenDocAndDeclaration(token)) {
57+
return i;
58+
}
59+
}
60+
return -1;
61+
}
62+
63+
private boolean isTriviaBetweenDocAndDeclaration(Token token) {
64+
int type = token.getType();
65+
if (type == WurstParser.HOTDOC_COMMENT
66+
|| type == WurstParser.LINE_COMMENT
67+
|| type == WurstParser.ML_COMMENT
68+
|| type == WurstParser.NL
69+
|| type == WurstParser.TAB
70+
|| type == WurstParser.SPACETAB) {
71+
return true;
72+
}
73+
return token.getChannel() != Token.DEFAULT_CHANNEL;
74+
}
75+
}

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/AutoCompleteTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,29 @@ public void nonConstantArrayDoesNotSuggestLength() {
451451
);
452452
}
453453

454+
@Test
455+
public void completionUsesHotdocComment() {
456+
CompletionTestData testData = input(
457+
"package test",
458+
"/** docs for foo */",
459+
"function fooBar()",
460+
"init",
461+
" foo|",
462+
"endpackage"
463+
);
464+
465+
CompletionList completions = calculateCompletions(testData);
466+
CompletionItem completion = completions.getItems().stream()
467+
.filter(c -> "fooBar".equals(c.getLabel()))
468+
.findFirst()
469+
.orElseThrow(() -> new AssertionError("fooBar completion not found"));
470+
471+
assertTrue(
472+
completion.getDocumentation() != null && completion.getDocumentation().getLeft().contains("docs for foo"),
473+
"completion documentation = " + completion.getDocumentation()
474+
);
475+
}
476+
454477
private void testCompletions(CompletionTestData testData, String... expectedCompletions) {
455478
testCompletions(testData, Arrays.asList(expectedCompletions));
456479
}

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/HoverTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.stream.Collectors;
1515

1616
import static org.testng.Assert.assertEquals;
17+
import static org.testng.Assert.assertTrue;
1718

1819
/**
1920
* tests the get definition functionality.
@@ -35,6 +36,19 @@ public void nonexistantModule() {
3536
assertEquals(Collections.emptyList(), text);
3637
}
3738

39+
@Test
40+
public void hoverUsesHotdocComment() {
41+
CompletionTestData testData = input(
42+
"package test",
43+
"/** this is hover doc */",
44+
"function fo|o()",
45+
"endpackage"
46+
);
47+
48+
List<String> text = testHoverText(testData);
49+
assertTrue(text.stream().anyMatch(s -> s.contains("this is hover doc")), "hover text = " + text);
50+
}
51+
3852

3953
private List<String> testHoverText(CompletionTestData testData) {
4054
Hover result = getHoverInfo(testData);

0 commit comments

Comments
 (0)