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
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ record Test(String completion, String expected, String fileContent, int caretPos
for (Test test : tests) {
CompletionItem completionItem = createCompletionItem( //
test.completion, //
CompletionItemKind.Class, //
CompletionItemKind.Snippet, //
new Range(new Position(0, test.caretPos()),
new Position(0, test.caretPos() + test.selectionLen())));
completionItem.setInsertTextFormat(InsertTextFormat.Snippet);
Expand Down Expand Up @@ -611,4 +611,33 @@ public void testContextInformationPositionUsesEditRangeStart() throws CoreExcept
// TextEdit starts at (0,2) so offset should be 0
assertEquals(editOffset, pos);
}

/**
* Ensures TM line-context variables are resolved from the viewer caret line,
* even when the TextEdit range is on a different line.
*/
@Test
public void testVariablesUseViewerLineNotEditRange() throws CoreException {
final CompletionItem completionItem = createCompletionItem( //
"$TM_LINE_INDEX $TM_LINE_NUMBER $TM_CURRENT_LINE", //
CompletionItemKind.Snippet, //
// Replace the entire 3rd line (line2) to avoid trailing leftovers
new Range(new Position(2, 0), new Position(2, 5)));
completionItem.setInsertTextFormat(InsertTextFormat.Snippet);
MockLanguageServer.INSTANCE.setCompletionList(new CompletionList(true, List.of(completionItem)));

ITextViewer viewer = TestUtils.openTextViewer(TestUtils.createUniqueTestFile(project, "line0\nline1\nline2"));

// Place caret on the first line (line 0) to drive variable resolution
viewer.setSelectedRange(0, 0);

// Invoke completion at the edit range line (start of line 2)
int editOffset = viewer.getDocument().get().indexOf("line2");
ICompletionProposal[] proposals = contentAssistProcessor.computeCompletionProposals(viewer, editOffset);
assertEquals(1, proposals.length);

((LSCompletionProposal) proposals[0]).apply(viewer, '\n', 0, editOffset);
// Variables should reflect caret line (line 0)
assertEquals("0 1 line0", viewer.getDocument().get().split("\n")[2]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -662,23 +662,42 @@ private String getVariableValue(String variableName) {
}
case TM_LINE_INDEX -> {
try {
yield Integer.toString(getTextEditRange().getStart().getLine()); // TODO probably wrong, should use viewer state
final var v = this.viewer;
if (v != null) {
int caretOffset = v.getSelectedRange().x;
yield Integer.toString(document.getLineOfOffset(caretOffset));
}
// fallback to text edit range if viewer not available
yield Integer.toString(getTextEditRange().getStart().getLine());
} catch (BadLocationException e) {
LanguageServerPlugin.logWarning(e.getMessage(), e);
yield ""; //$NON-NLS-1$
}
}
case TM_LINE_NUMBER -> {
try {
yield Integer.toString(getTextEditRange().getStart().getLine() + 1); // TODO probably wrong, should use viewer state
final var v = this.viewer;
if (v != null) {
int caretOffset = v.getSelectedRange().x;
yield Integer.toString(document.getLineOfOffset(caretOffset) + 1);
}
// fallback to text edit range if viewer not available
yield Integer.toString(getTextEditRange().getStart().getLine() + 1);
} catch (BadLocationException e) {
LanguageServerPlugin.logWarning(e.getMessage(), e);
yield ""; //$NON-NLS-1$
}
}
case TM_CURRENT_LINE -> { // TODO probably wrong, should use viewer state
case TM_CURRENT_LINE -> {
try {
int currentLineIndex = getTextEditRange().getStart().getLine();
int currentLineIndex;
final var v = this.viewer;
if (v != null) {
int caretOffset = v.getSelectedRange().x;
currentLineIndex = document.getLineOfOffset(caretOffset);
} else {
currentLineIndex = getTextEditRange().getStart().getLine();
}
IRegion lineInformation = document.getLineInformation(currentLineIndex);
String line = document.get(lineInformation.getOffset(), lineInformation.getLength());
yield line;
Expand Down