diff --git a/.gitignore b/.gitignore
index e14af20..ff3b7ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,4 @@ node_modules
.vscode-test/
*.vsix
-.vscode
-.idea
\ No newline at end of file
+.idea
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..72c7609
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,17 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "args": [
+ "--extensionDevelopmentPath=${workspaceFolder}"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/dist/**/*.js"
+ ],
+ "preLaunchTask": "npm: compile"
+ }
+ ]
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..8df9478
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,12 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "npm: compile",
+ "type": "npm",
+ "script": "compile",
+ "group": "build",
+ "problemMatcher": ["$tsc"]
+ }
+ ]
+}
diff --git a/package.json b/package.json
index dfd0d70..e189a80 100644
--- a/package.json
+++ b/package.json
@@ -21,10 +21,12 @@
],
"scripts": {
"vscode:prepublish": "npm run package",
+ "vscode:publish": "npx vsce package",
"compile": "webpack",
"watch": "webpack --watch",
"package": "webpack --mode production --devtool hidden-source-map",
- "lint": "eslint src --ext ts"
+ "lint": "eslint src --ext ts",
+ "lint:fix": "eslint src --ext ts --fix"
},
"devDependencies": {
"@types/glob": "^8.0.0",
diff --git a/resources/implement.svg b/resources/implement.svg
new file mode 100644
index 0000000..fcae3db
--- /dev/null
+++ b/resources/implement.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/src/AnnotateLensProvider.ts b/src/AnnotateLensProvider.ts
index d0c19e2..e0d624c 100644
--- a/src/AnnotateLensProvider.ts
+++ b/src/AnnotateLensProvider.ts
@@ -2,6 +2,7 @@ import * as vscode from "vscode";
import { Annotation } from "./Annotation";
import { AnnotationLens } from "./AnnotationLens";
import { SymbolInfo } from "./SymbolInfo";
+import { getImplementDecoration } from "./decorations";
export class AnnotationLensProvider
implements vscode.CodeLensProvider
@@ -9,15 +10,18 @@ export class AnnotationLensProvider
public async provideCodeLenses(
document: vscode.TextDocument
): Promise {
+ const activeEditor = vscode.window.activeTextEditor;
+ if (!activeEditor) {
+ return [];
+ }
+
const goSymbols = await this.getGoSymbols(document);
+ const decorationLocations: vscode.Range[] = [];
+
const results: AnnotationLens[] = [];
for (const goSymbol of goSymbols) {
const symbolInfo = await SymbolInfo.create(goSymbol);
- const activeEditor = vscode.window.activeTextEditor;
- if (!activeEditor) {
- return [];
- }
const locations = await this.getSymbolLocations(activeEditor, symbolInfo) ?? [];
const symbols = await Promise.all(locations.map(SymbolInfo.getSymbol));
@@ -27,16 +31,67 @@ export class AnnotationLensProvider
const annotation = new Annotation(symbolInfo.symbol, symbols);
results.push(new AnnotationLens(annotation));
+
+ const decorationRange = new vscode.Range(
+ symbolInfo.symbol.location.range.start,
+ symbolInfo.symbol.location.range.start,
+ );
+ decorationLocations.push(
+ decorationRange,
+ );
+
+ for (const child of symbolInfo.symbol.children ?? []) {
+ if (child.kind !== vscode.SymbolKind.Method) {
+ continue;
+ }
+
+ // For methods, get implementation locations directly
+ const methodLocations = await vscode.commands.executeCommand(
+ "vscode.executeImplementationProvider",
+ activeEditor.document.uri,
+ child.range.start
+ ) ?? [];
+
+ if (methodLocations.length > 0) {
+ const methodSymbols = await Promise.all(methodLocations.map(SymbolInfo.getSymbol));
+
+ // Create location from document and child range
+ const location = new vscode.Location(activeEditor.document.uri, child.range);
+
+ // Convert the child into the combined type needed for Annotation
+ const combinedSymbol = {
+ ...child,
+ location,
+ containerName: symbolInfo.symbol.name
+ } as vscode.SymbolInformation & vscode.DocumentSymbol;
+
+ const methodAnnotation = new Annotation(combinedSymbol, methodSymbols);
+ results.push(new AnnotationLens(methodAnnotation));
+ }
+ }
}
+ activeEditor.setDecorations(
+ getImplementDecoration(),
+ decorationLocations,
+ );
+
+
return results;
}
private async getSymbolLocations(te: vscode.TextEditor, si: SymbolInfo): Promise {
+ let position = si.symbol.location.range.start;
+ if (si.symbol.kind === vscode.SymbolKind.Method) {
+ position = new vscode.Position(
+ si.symbol.selectionRange.start.line,
+ si.symbol.selectionRange.start.character + 1,
+ );
+ }
return vscode.commands.executeCommand(
"vscode.executeImplementationProvider",
te.document.uri,
- si.symbol.location.range.start
+ position,
);
}
@@ -47,7 +102,8 @@ export class AnnotationLensProvider
(symbol) =>
symbol.kind === vscode.SymbolKind.Class ||
symbol.kind === vscode.SymbolKind.Struct ||
- symbol.kind === vscode.SymbolKind.Interface
+ symbol.kind === vscode.SymbolKind.Interface ||
+ symbol.kind === vscode.SymbolKind.Method
);
return symbols;
}
diff --git a/src/SymbolInfo.ts b/src/SymbolInfo.ts
index 162837a..a21321e 100644
--- a/src/SymbolInfo.ts
+++ b/src/SymbolInfo.ts
@@ -1,4 +1,4 @@
-import * as vscode from "vscode";
+import * as vscode from 'vscode';
export class SymbolInfo {
public readonly symbol: vscode.SymbolInformation & vscode.DocumentSymbol;
@@ -15,9 +15,9 @@ export class SymbolInfo {
): Promise {
const documentSymbols = (await vscode.commands.executeCommand<
(vscode.SymbolInformation & vscode.DocumentSymbol)[]
- >("vscode.executeDocumentSymbolProvider", location.uri))!;
+ >('vscode.executeDocumentSymbolProvider', location.uri))!;
return documentSymbols.find((documentSymbol) =>
- documentSymbol.range.start.isEqual(location.range.start)
+ documentSymbol.range.contains(location.range)
) as vscode.SymbolInformation & vscode.DocumentSymbol;
}
@@ -29,9 +29,10 @@ export class SymbolInfo {
if (
this.symbol.kind !== vscode.SymbolKind.Class &&
this.symbol.kind !== vscode.SymbolKind.Struct &&
- this.symbol.kind !== vscode.SymbolKind.Interface
+ this.symbol.kind !== vscode.SymbolKind.Interface &&
+ this.symbol.kind !== vscode.SymbolKind.Method
) {
- throw new Error("Expected struct or interface");
+ throw new Error('Expected struct or interface');
}
}
}
diff --git a/src/decorations.ts b/src/decorations.ts
new file mode 100644
index 0000000..3feeeb8
--- /dev/null
+++ b/src/decorations.ts
@@ -0,0 +1,11 @@
+
+import * as vscode from "vscode";
+
+let implementDecoration = vscode.window.createTextEditorDecorationType({
+ gutterIconPath: __dirname + "/../resources/implement.svg",
+ fontWeight: "bold",
+});
+
+export function getImplementDecoration() {
+ return implementDecoration;
+}
\ No newline at end of file