Skip to content
Open
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
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ node_modules
.vscode-test/
*.vsix

.vscode
.idea
.idea
17 changes: 17 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -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"
}
]
}
12 changes: 12 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "npm: compile",
"type": "npm",
"script": "compile",
"group": "build",
"problemMatcher": ["$tsc"]
}
]
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
6 changes: 6 additions & 0 deletions resources/implement.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 62 additions & 6 deletions src/AnnotateLensProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ 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<AnnotationLens>
{
public async provideCodeLenses(
document: vscode.TextDocument
): Promise<vscode.CodeLens[]> {
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));
Expand All @@ -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.Location[]>(
"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<vscode.Location[]> {
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.Location[]>(
"vscode.executeImplementationProvider",
te.document.uri,
si.symbol.location.range.start
position,
);
}

Expand All @@ -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;
}
Expand Down
11 changes: 6 additions & 5 deletions src/SymbolInfo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as vscode from "vscode";
import * as vscode from 'vscode';

export class SymbolInfo {
public readonly symbol: vscode.SymbolInformation & vscode.DocumentSymbol;
Expand All @@ -15,9 +15,9 @@ export class SymbolInfo {
): Promise<vscode.SymbolInformation & vscode.DocumentSymbol> {
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;
}

Expand All @@ -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');
}
}
}
11 changes: 11 additions & 0 deletions src/decorations.ts
Original file line number Diff line number Diff line change
@@ -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;
}