Skip to content

Commit 0078e3f

Browse files
committed
Add Hover for Variables
1 parent ca1f1fc commit 0078e3f

4 files changed

Lines changed: 54 additions & 24 deletions

File tree

client/src/services/context.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,23 @@ import { getOriginalVariableName } from "../utils/utils";
55

66
export function handleContext(context: LJContext) {
77
extension.context = context;
8-
updateContextForSelection(extension.currentSelection);
8+
if (!extension.file || !extension.currentSelection) return;
9+
10+
// update variables based on new context in current selection
11+
const { allVars, visibleVars } = getSelectionContextVariables(extension.file, extension.currentSelection);
12+
extension.context.visibleVars = visibleVars;
13+
extension.context.allVars = allVars;
914
extension.webview.sendMessage({ type: "context", context: extension.context, errorAtCursor: extension.errorAtCursor });
1015
}
1116

12-
export function updateContextForSelection(selection: Range) {
13-
if (!selection) return;
14-
15-
const globalVars = extension.context.globalVars || [];
16-
const localVars = extension.context.localVars || [];
17-
const variablesInScope = getVariablesInScope(localVars, extension.file, selection);
18-
const visibleVarsByPosition = getVisibleVariables(variablesInScope, extension.file, selection, false);
19-
const visibleVarsByAnnotationPosition = getVisibleVariables(variablesInScope, extension.file, selection, true);
17+
export function getSelectionContextVariables(file: string, selection: Range): { visibleVars: LJVariable[]; allVars: LJVariable[] } {
18+
const globalVars = extension.context?.globalVars || [];
19+
const localVars = extension.context?.localVars || [];
20+
const variablesInScope = getVariablesInScope(localVars, file, selection);
21+
const visibleVarsByPosition = getVisibleVariables(variablesInScope, file, selection, false);
22+
const visibleVarsByAnnotationPosition = getVisibleVariables(variablesInScope, file, selection, true);
2023
const allVars = sortVariables(normalizeVariableRefinements([...globalVars, ...visibleVarsByPosition]));
21-
extension.context.visibleVars = visibleVarsByAnnotationPosition;
22-
extension.context.allVars = allVars;
24+
return { visibleVars: visibleVarsByAnnotationPosition, allVars };
2325
}
2426

2527
function getVariablesInScope(variables: LJVariable[], file: string, selection: Range): LJVariable[] {

client/src/services/events.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as vscode from 'vscode';
22
import { extension } from '../state';
33
import { updateStateMachine } from './state-machine';
44
import { SELECTION_DEBOUNCE_MS } from '../utils/constants';
5-
import { normalizeRange, updateContextForSelection } from './context';
5+
import { getSelectionContextVariables, normalizeRange } from './context';
66
import { normalizeFilePath } from '../utils/utils';
77
import { Range } from '../types/context';
88
import { updateErrorAtCursor } from './diagnostics';
@@ -68,8 +68,10 @@ function handleContextUpdate(selection: vscode.Selection) {
6868
colEnd: selection.end.character
6969
};
7070
const normalizedRange = normalizeRange(range);
71+
const { allVars, visibleVars } = getSelectionContextVariables(extension.file, normalizedRange);
7172
extension.currentSelection = normalizedRange;
72-
updateContextForSelection(normalizedRange);
73+
extension.context.visibleVars = visibleVars;
74+
extension.context.allVars = allVars;
7375
updateErrorAtCursor();
7476
extension.webview?.sendMessage({ type: "context", context: extension.context, errorAtCursor: extension.errorAtCursor });
7577
}

client/src/services/hover.ts

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,48 @@
11
import * as vscode from 'vscode';
22
import { extension } from '../state';
3+
import type { Range, LJVariable } from '../types/context';
4+
import { getSelectionContextVariables, rangesIntersect } from './context';
5+
import { getOriginalVariableName, normalizeFilePath } from '../utils/utils';
36

47
/**
58
* Initializes hover provider for LiquidJava diagnostics
69
*/
710
export function registerHover() {
811
vscode.languages.registerHoverProvider('java', {
912
provideHover(document, position) {
10-
// if webview is visible, do not show hover
11-
if (extension.webview?.isVisible()) return null;
12-
13-
// get lj diagnostic at the current position
14-
const diagnostics = vscode.languages.getDiagnostics(document.uri);
15-
const diagnostic = diagnostics.find(d => d.range.contains(position) && d.source === 'liquidjava');
16-
if (!diagnostic) return null;
17-
18-
// create hover content with link to open webview
1913
const hoverContent = new vscode.MarkdownString();
2014
hoverContent.isTrusted = true;
21-
hoverContent.appendMarkdown(`\n\n[Open LiquidJava view](command:liquidjava.showView) for more details.`);
15+
16+
const variable = getHoveredVariable(document, position);
17+
if (variable && variable.mainRefinement && variable.mainRefinement !== 'true')
18+
hoverContent.appendCodeblock(`@Refinement(${JSON.stringify(variable.mainRefinement)})`, 'java');
19+
20+
const diagnostics = vscode.languages.getDiagnostics(document.uri);
21+
const containsDiagnostic = !!diagnostics.find(d => d.range.contains(position) && d.source === 'liquidjava');
22+
if (containsDiagnostic) {
23+
if (hoverContent.value.length > 0) hoverContent.appendMarkdown(`\n\n`);
24+
hoverContent.appendMarkdown(`[Open LiquidJava view](command:liquidjava.showView) for more details.`);
25+
}
26+
if (hoverContent.value.length === 0) return null;
2227
return new vscode.Hover(hoverContent);
2328
}
2429
});
2530
}
31+
32+
function getHoveredVariable(document: vscode.TextDocument, position: vscode.Position): LJVariable | null {
33+
if (!extension.context) return null;
34+
35+
const wordRange = document.getWordRangeAtPosition(position, /[#]?[A-Za-z_][A-Za-z0-9_#]*/);
36+
if (!wordRange) return null;
37+
38+
const hoveredWord = document.getText(wordRange);
39+
const file = normalizeFilePath(document.uri.fsPath);
40+
const hoveredRange: Range = {
41+
lineStart: wordRange.start.line,
42+
colStart: wordRange.start.character,
43+
lineEnd: wordRange.end.line,
44+
colEnd: wordRange.end.character
45+
};
46+
const { allVars } = getSelectionContextVariables(file, hoveredRange);
47+
return allVars.find(variable => getOriginalVariableName(variable.name) === hoveredWord);
48+
}

client/src/utils/utils.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,10 @@ export function getSimpleName(qualifiedName: string): string {
130130
}
131131

132132
export function getOriginalVariableName(name: string): string {
133-
return name.split("_")[0].replace(/^#/, '');
133+
if (name.startsWith("this#")) return name.replace(/^this#/, '');
134+
if (name.startsWith("#")) return name.split("_")[0].replace(/^#/, '');
135+
return name;
136+
134137
}
135138

136139
export function normalizeFilePath(fsPath: string): string {

0 commit comments

Comments
 (0)