diff --git a/packages/roboview/roboview/models/robot_parsing/local_keyword_parsing.py b/packages/roboview/roboview/models/robot_parsing/local_keyword_parsing.py
index c165365..6b179d0 100644
--- a/packages/roboview/roboview/models/robot_parsing/local_keyword_parsing.py
+++ b/packages/roboview/roboview/models/robot_parsing/local_keyword_parsing.py
@@ -64,6 +64,7 @@ def visit_Keyword(self, node: Keyword) -> None: # noqa: N802
source=self.file_path.as_posix(),
validation_str_without_prefix=node.name.lower().replace(" ", "").replace("_", ""),
validation_str_with_prefix=keyword_name_with_prefix.lower().replace(" ", "").replace("_", ""),
+ line_number=node.lineno,
)
)
except AttributeError:
diff --git a/packages/roboview/roboview/schemas/domain/keywords.py b/packages/roboview/roboview/schemas/domain/keywords.py
index 2df9f63..ee81013 100644
--- a/packages/roboview/roboview/schemas/domain/keywords.py
+++ b/packages/roboview/roboview/schemas/domain/keywords.py
@@ -21,6 +21,7 @@ class KeywordProperties(BaseModel):
called_keywords: list[str] | None = Field(
description="List of keywords that are called by the actual Keyword", default=[]
)
+ line_number: int | None = Field(description="Line number where the keyword is defined", default=None)
class KeywordUsage(BaseModel):
@@ -34,6 +35,7 @@ class KeywordUsage(BaseModel):
source: str = Field(description="Path of the file, where the keyword is defined as POSIX")
file_usages: int = Field(description="Usage of the keyword, in the selected file")
total_usages: int = Field(description="Total usage of the keyword across the whole project")
+ line_number: int | None = Field(description="Line number where the keyword is defined", default=None)
class SimilarKeyword(BaseModel):
diff --git a/packages/roboview/roboview/services/keyword_usage_service.py b/packages/roboview/roboview/services/keyword_usage_service.py
index 867eb6c..48d65d1 100644
--- a/packages/roboview/roboview/services/keyword_usage_service.py
+++ b/packages/roboview/roboview/services/keyword_usage_service.py
@@ -72,6 +72,7 @@ def get_keywords_with_global_usage_for_file(self, file_path: Path, keyword_type:
kw, file_path.as_posix()
),
total_usages=self._get_global_keyword_usage_for_target_keyword(kw),
+ line_number=keyword.line_number,
)
)
except Exception:
@@ -164,6 +165,7 @@ def get_keywords_without_documentation(self) -> list[KeywordUsage]:
total_usages=self._get_global_keyword_usage_for_target_keyword(
entry.keyword_name_with_prefix
),
+ line_number=entry.line_number,
)
)
except Exception:
@@ -198,6 +200,7 @@ def get_keywords_without_usages(self) -> list[KeywordUsage]:
source=entry.source,
file_usages=total_usages,
total_usages=total_usages,
+ line_number=entry.line_number,
)
)
except Exception:
@@ -241,6 +244,7 @@ def get_potential_duplicate_keywords(self, keyword_sim_service: KeywordSimilarit
total_usages=self._get_global_keyword_usage_for_target_keyword(
entry.keyword_name_with_prefix
),
+ line_number=entry.line_number,
)
)
except Exception:
@@ -334,6 +338,7 @@ def _get_external_or_builtin_keywords_with_usages(self) -> list[KeywordUsage]:
total_usages=self._get_global_keyword_usage_for_target_keyword(
entry.keyword_name_with_prefix
),
+ line_number=entry.line_number,
)
)
except Exception:
@@ -375,6 +380,7 @@ def _get_user_defined_keywords_with_usages(self) -> list[KeywordUsage]:
total_usages=self._get_global_keyword_usage_for_target_keyword(
entry.keyword_name_with_prefix
),
+ line_number=entry.line_number,
)
)
except Exception:
diff --git a/vscode-integration/package-lock.json b/vscode-integration/package-lock.json
index a28e50f..cbc1174 100644
--- a/vscode-integration/package-lock.json
+++ b/vscode-integration/package-lock.json
@@ -1,17 +1,18 @@
{
"name": "roboview",
- "version": "0.0.3",
+ "version": "0.0.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "roboview",
- "version": "0.0.3",
+ "version": "0.0.4",
"dependencies": {
- "axios": "^1.7.9",
- "dotenv": "^17.3.1"
+ "axios": "^1.7.9"
},
"devDependencies": {
+ "@types/axios": "^0.9.36",
+ "@types/dotenv": "^6.1.1",
"@types/mocha": "^10.0.10",
"@types/node": "25.x",
"@types/vscode": "^1.93.0",
@@ -20,6 +21,7 @@
"@vscode/test-cli": "^0.0.11",
"@vscode/test-electron": "^2.5.2",
"@vscode/vsce": "^3.7.1",
+ "dotenv": "^17.4.2",
"esbuild": "^0.27.3",
"eslint": "^10.0.2",
"eslint-config-prettier": "^10.1.8",
@@ -1382,6 +1384,23 @@
"@textlint/ast-node-types": "15.5.2"
}
},
+ "node_modules/@types/axios": {
+ "version": "0.9.36",
+ "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.9.36.tgz",
+ "integrity": "sha512-NLOpedx9o+rxo/X5ChbdiX6mS1atE4WHmEEIcR9NLenRVa5HoVjAvjafwU3FPTqnZEstpoqCaW7fagqSoTDNeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/dotenv": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-6.1.1.tgz",
+ "integrity": "sha512-ftQl3DtBvqHl9L16tpqqzA4YzCSXZfi7g8cQceTz5rOlYtk/IZbFjAv3mLOQlNIgOaylCQWQoBdDQHPgEBJPHg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/esrecurse": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
@@ -2821,9 +2840,10 @@
}
},
"node_modules/dotenv": {
- "version": "17.3.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
- "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
+ "version": "17.4.2",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
+ "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
+ "dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
diff --git a/vscode-integration/package.json b/vscode-integration/package.json
index cdefc9b..83b3a5d 100644
--- a/vscode-integration/package.json
+++ b/vscode-integration/package.json
@@ -84,10 +84,11 @@
"test": "vscode-test"
},
"dependencies": {
- "axios": "^1.7.9",
- "dotenv": "^17.3.1"
+ "axios": "^1.7.9"
},
"devDependencies": {
+ "@types/axios": "^0.9.36",
+ "@types/dotenv": "^6.1.1",
"@types/mocha": "^10.0.10",
"@types/node": "25.x",
"@types/vscode": "^1.93.0",
@@ -96,6 +97,7 @@
"@vscode/test-cli": "^0.0.11",
"@vscode/test-electron": "^2.5.2",
"@vscode/vsce": "^3.7.1",
+ "dotenv": "^17.4.2",
"esbuild": "^0.27.3",
"eslint": "^10.0.2",
"eslint-config-prettier": "^10.1.8",
diff --git a/vscode-integration/src/roboViewPanel.ts b/vscode-integration/src/roboViewPanel.ts
index de6019d..44839d6 100644
--- a/vscode-integration/src/roboViewPanel.ts
+++ b/vscode-integration/src/roboViewPanel.ts
@@ -6,6 +6,8 @@ import {
Uri,
ViewColumn,
Range,
+ TextEditorRevealType,
+ Position,
} from "vscode";
import axios from "axios";
import { getUri } from "./utils/getUri";
@@ -170,12 +172,16 @@ export class RoboViewPanel {
if (filePath) {
const fileUri = Uri.file(filePath);
- window.showTextDocument(fileUri, {
+ const position = new Position(line - 1, 0);
+ const range = new Range(position, position);
+
+ const editor = await window.showTextDocument(fileUri, {
preview: false,
viewColumn: ViewColumn.Active,
- selection:
- line > 1 ? new Range(line - 1, 0, line - 1, 0) : undefined,
+ selection: range,
});
+
+ editor.revealRange(range, TextEditorRevealType.InCenter);
}
break;
}
diff --git a/vscode-integration/webview-ui/src/app/keyword-usage-panel/main-content-kw.tsx b/vscode-integration/webview-ui/src/app/keyword-usage-panel/main-content-kw.tsx
index 211fca6..fb3fe80 100644
--- a/vscode-integration/webview-ui/src/app/keyword-usage-panel/main-content-kw.tsx
+++ b/vscode-integration/webview-ui/src/app/keyword-usage-panel/main-content-kw.tsx
@@ -177,12 +177,12 @@ export function MainContentKeywordUsage({
pageStartIndex + PAGE_SIZE,
);
- const handleSourceClick = (event: React.MouseEvent, filePath: string) => {
- if (event.ctrlKey || event.metaKey) {
- event.stopPropagation();
- vscode.postMessage({ command: "openFile", filePath });
- }
- };
+ const handleSourceClick = (event: React.MouseEvent, filePath: string, lineNumber: number) => {
+ if (event.ctrlKey || event.metaKey) {
+ event.stopPropagation();
+ vscode.postMessage({ command: "openFile", filePath, line: lineNumber });
+ }
+};
if (showNoFileSelected) {
return ;
@@ -318,7 +318,7 @@ export function MainContentKeywordUsage({
- handleSourceClick(event, keyword.source)
+ handleSourceClick(event, keyword.source, keyword.line_number)
}
title={keyword.source}
>
diff --git a/vscode-integration/webview-ui/src/types/keywords.ts b/vscode-integration/webview-ui/src/types/keywords.ts
index 71b292e..0e04857 100644
--- a/vscode-integration/webview-ui/src/types/keywords.ts
+++ b/vscode-integration/webview-ui/src/types/keywords.ts
@@ -17,6 +17,7 @@ export interface Keyword {
source: string;
file_usages: number;
total_usages: number;
+ line_number: number;
}
export interface KeywordCounts {