wafer-lsp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wafer_lsp-0.1.0/.gitignore +85 -0
- wafer_lsp-0.1.0/PKG-INFO +57 -0
- wafer_lsp-0.1.0/README.md +37 -0
- wafer_lsp-0.1.0/pyproject.toml +67 -0
- wafer_lsp-0.1.0/src/wafer_lsp/__init__.py +1 -0
- wafer_lsp-0.1.0/src/wafer_lsp/__main__.py +9 -0
- wafer_lsp-0.1.0/src/wafer_lsp/analyzers/__init__.py +0 -0
- wafer_lsp-0.1.0/src/wafer_lsp/analyzers/compiler_integration.py +16 -0
- wafer_lsp-0.1.0/src/wafer_lsp/analyzers/docs_index.py +36 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/__init__.py +0 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/code_action.py +48 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/code_lens.py +48 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/completion.py +6 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/diagnostics.py +16 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/document_symbol.py +87 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/hover.py +215 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/inlay_hint.py +65 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/semantic_tokens.py +124 -0
- wafer_lsp-0.1.0/src/wafer_lsp/handlers/workspace_symbol.py +87 -0
- wafer_lsp-0.1.0/src/wafer_lsp/languages/README.md +195 -0
- wafer_lsp-0.1.0/src/wafer_lsp/languages/__init__.py +17 -0
- wafer_lsp-0.1.0/src/wafer_lsp/languages/converter.py +88 -0
- wafer_lsp-0.1.0/src/wafer_lsp/languages/detector.py +34 -0
- wafer_lsp-0.1.0/src/wafer_lsp/languages/parser_manager.py +33 -0
- wafer_lsp-0.1.0/src/wafer_lsp/languages/registry.py +99 -0
- wafer_lsp-0.1.0/src/wafer_lsp/languages/types.py +37 -0
- wafer_lsp-0.1.0/src/wafer_lsp/parsers/__init__.py +18 -0
- wafer_lsp-0.1.0/src/wafer_lsp/parsers/base_parser.py +9 -0
- wafer_lsp-0.1.0/src/wafer_lsp/parsers/cuda_parser.py +95 -0
- wafer_lsp-0.1.0/src/wafer_lsp/parsers/cutedsl_parser.py +114 -0
- wafer_lsp-0.1.0/src/wafer_lsp/server.py +58 -0
- wafer_lsp-0.1.0/src/wafer_lsp/services/__init__.py +21 -0
- wafer_lsp-0.1.0/src/wafer_lsp/services/analysis_service.py +22 -0
- wafer_lsp-0.1.0/src/wafer_lsp/services/docs_service.py +40 -0
- wafer_lsp-0.1.0/src/wafer_lsp/services/document_service.py +20 -0
- wafer_lsp-0.1.0/src/wafer_lsp/services/hover_service.py +237 -0
- wafer_lsp-0.1.0/src/wafer_lsp/services/language_registry_service.py +26 -0
- wafer_lsp-0.1.0/src/wafer_lsp/services/position_service.py +77 -0
- wafer_lsp-0.1.0/src/wafer_lsp/utils/__init__.py +0 -0
- wafer_lsp-0.1.0/src/wafer_lsp/utils/lsp_helpers.py +79 -0
- wafer_lsp-0.1.0/tests/__init__.py +1 -0
- wafer_lsp-0.1.0/tests/test_converter.py +121 -0
- wafer_lsp-0.1.0/tests/test_cutedsl_parser.py +60 -0
- wafer_lsp-0.1.0/tests/test_language_detector.py +59 -0
- wafer_lsp-0.1.0/tests/test_lsp_handlers.py +57 -0
- wafer_lsp-0.1.0/tests/test_parser_manager.py +57 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
*.pyc
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*$py.class
|
|
6
|
+
*.so
|
|
7
|
+
.Python
|
|
8
|
+
*.egg-info/
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
ENV/
|
|
15
|
+
|
|
16
|
+
# Distribution / packaging
|
|
17
|
+
dist/
|
|
18
|
+
build/
|
|
19
|
+
*.egg
|
|
20
|
+
|
|
21
|
+
# IDE
|
|
22
|
+
.vscode/
|
|
23
|
+
.cursor/
|
|
24
|
+
.idea/
|
|
25
|
+
*.swp
|
|
26
|
+
*.swo
|
|
27
|
+
*~
|
|
28
|
+
|
|
29
|
+
# OS
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
|
32
|
+
|
|
33
|
+
# Temporary files
|
|
34
|
+
*.tmp
|
|
35
|
+
tests.txt
|
|
36
|
+
output.txt
|
|
37
|
+
|
|
38
|
+
# Evaluation results
|
|
39
|
+
experiments/emilio/cutedsl-quack-eval/eval_results/*.txt
|
|
40
|
+
experiments/emilio/cutedsl-quack-eval/eval_results/*.json
|
|
41
|
+
experiments/emilio/cutedsl-quack-eval/eval_results/*.py
|
|
42
|
+
research/evals/kernelbench/results/
|
|
43
|
+
wafer_artifacts/
|
|
44
|
+
**/wafer_artifacts/
|
|
45
|
+
/.deps/
|
|
46
|
+
|
|
47
|
+
# Local config files
|
|
48
|
+
services/docs-tool/config.yaml
|
|
49
|
+
|
|
50
|
+
# Environment files with secrets
|
|
51
|
+
.env
|
|
52
|
+
.env.local
|
|
53
|
+
.env.*.local
|
|
54
|
+
node_modules/
|
|
55
|
+
.vscode-test/
|
|
56
|
+
|
|
57
|
+
# npm artifacts (using yarn)
|
|
58
|
+
package-lock.json
|
|
59
|
+
npm-debug.log*
|
|
60
|
+
.npm/
|
|
61
|
+
.npmrc
|
|
62
|
+
|
|
63
|
+
# Yarn artifacts
|
|
64
|
+
.yarn/install-state.gz
|
|
65
|
+
|
|
66
|
+
# NSYS report files (can be very large)
|
|
67
|
+
*.nsys-rep
|
|
68
|
+
|
|
69
|
+
# Turbo build cache
|
|
70
|
+
.turbo/
|
|
71
|
+
**/.turbo/
|
|
72
|
+
|
|
73
|
+
# Supabase CLI temp files
|
|
74
|
+
supabase/.branches/
|
|
75
|
+
supabase/.temp/
|
|
76
|
+
**/supabase/.branches/
|
|
77
|
+
**/supabase/.temp/
|
|
78
|
+
|
|
79
|
+
# Eval results (generated, large)
|
|
80
|
+
research/evals/kernelbench/kernelbench/results/
|
|
81
|
+
research/evals/retrieval_eval_project/retrieval_eval/results/
|
|
82
|
+
research/evals/retrieval_eval_project/*.log
|
|
83
|
+
|
|
84
|
+
# Wafer extension trace files
|
|
85
|
+
.wafer/traces/
|
wafer_lsp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wafer-lsp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Language Server Protocol server for GPU programming languages
|
|
5
|
+
Author-email: Wafer <support@wafer.ai>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: c++,cuda,cutedsl,gpu,language-server,lsp
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE)
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Requires-Dist: lsprotocol>=2024.0.0
|
|
17
|
+
Requires-Dist: pygls>=1.0.0
|
|
18
|
+
Requires-Dist: wafer-core
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Wafer LSP
|
|
22
|
+
|
|
23
|
+
Language Server Protocol server for CuTeDSL (Python GPU programming).
|
|
24
|
+
|
|
25
|
+
**Beta Feature**: Currently only available when Beta Mode is enabled in VS Code settings.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **Hover Information**: Shows kernel and layout information with compiler analysis when hovering over CuTeDSL code
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install wafer-lsp
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
### VS Code Extension
|
|
40
|
+
|
|
41
|
+
The LSP server is integrated into the `wevin-extension` VS Code extension. It starts automatically when Beta Mode is enabled.
|
|
42
|
+
|
|
43
|
+
### Standalone
|
|
44
|
+
|
|
45
|
+
For Neovim or other editors:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python -m wafer_lsp
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Supported Languages
|
|
52
|
+
|
|
53
|
+
- **CuTeDSL**: Python files with `@cute.kernel` decorators
|
|
54
|
+
|
|
55
|
+
## Architecture
|
|
56
|
+
|
|
57
|
+
The LSP server uses a modular language registry system. Currently supports CuTeDSL only. See `languages/README.md` for details on adding more languages.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Wafer LSP
|
|
2
|
+
|
|
3
|
+
Language Server Protocol server for CuTeDSL (Python GPU programming).
|
|
4
|
+
|
|
5
|
+
**Beta Feature**: Currently only available when Beta Mode is enabled in VS Code settings.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Hover Information**: Shows kernel and layout information with compiler analysis when hovering over CuTeDSL code
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install wafer-lsp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### VS Code Extension
|
|
20
|
+
|
|
21
|
+
The LSP server is integrated into the `wevin-extension` VS Code extension. It starts automatically when Beta Mode is enabled.
|
|
22
|
+
|
|
23
|
+
### Standalone
|
|
24
|
+
|
|
25
|
+
For Neovim or other editors:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python -m wafer_lsp
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Supported Languages
|
|
32
|
+
|
|
33
|
+
- **CuTeDSL**: Python files with `@cute.kernel` decorators
|
|
34
|
+
|
|
35
|
+
## Architecture
|
|
36
|
+
|
|
37
|
+
The LSP server uses a modular language registry system. Currently supports CuTeDSL only. See `languages/README.md` for details on adding more languages.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "wafer-lsp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Language Server Protocol server for GPU programming languages"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"pygls>=1.0.0",
|
|
9
|
+
"lsprotocol>=2024.0.0",
|
|
10
|
+
"wafer-core", # For compiler analyzer
|
|
11
|
+
]
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Wafer", email = "support@wafer.ai" }
|
|
14
|
+
]
|
|
15
|
+
license = { text = "MIT" }
|
|
16
|
+
keywords = ["lsp", "language-server", "gpu", "cuda", "cutedsl", "c++"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
|
+
"Topic :: Text Editors :: Integrated Development Environments (IDE)",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[build-system]
|
|
28
|
+
requires = ["hatchling"]
|
|
29
|
+
build-backend = "hatchling.build"
|
|
30
|
+
|
|
31
|
+
[project.scripts]
|
|
32
|
+
wafer-lsp = "wafer_lsp.__main__:main"
|
|
33
|
+
|
|
34
|
+
[tool.hatch.build.targets.wheel]
|
|
35
|
+
packages = ["src/wafer_lsp"]
|
|
36
|
+
|
|
37
|
+
[tool.ruff]
|
|
38
|
+
line-length = 100
|
|
39
|
+
target-version = "py312"
|
|
40
|
+
preview = true
|
|
41
|
+
|
|
42
|
+
[tool.ruff.lint]
|
|
43
|
+
select = [
|
|
44
|
+
"E", # pycodestyle errors
|
|
45
|
+
"W", # pycodestyle warnings
|
|
46
|
+
"F", # pyflakes
|
|
47
|
+
"I", # isort
|
|
48
|
+
"B", # flake8-bugbear
|
|
49
|
+
"C4", # flake8-comprehensions
|
|
50
|
+
"UP", # pyupgrade
|
|
51
|
+
"ARG", # flake8-unused-arguments
|
|
52
|
+
"SIM", # flake8-simplify
|
|
53
|
+
"PLR", # pylint refactor
|
|
54
|
+
"PLW", # pylint warnings
|
|
55
|
+
"PT", # flake8-pytest-style
|
|
56
|
+
"RUF", # Ruff-specific rules
|
|
57
|
+
]
|
|
58
|
+
ignore = [
|
|
59
|
+
"E501", # line too long (handled by formatter)
|
|
60
|
+
"B008", # do not perform function calls in argument defaults
|
|
61
|
+
"PLR0913", # too many arguments
|
|
62
|
+
"PLR2004", # magic value used in comparison
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[tool.ruff.format]
|
|
66
|
+
quote-style = "double"
|
|
67
|
+
indent-style = "space"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
File without changes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
_analysis_cache: dict[str, dict[str, Any]] = {}
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_analysis_for_kernel(uri: str, kernel_name: str) -> dict[str, Any] | None:
|
|
7
|
+
cache_key = f"{uri}:{kernel_name}"
|
|
8
|
+
|
|
9
|
+
if cache_key in _analysis_cache:
|
|
10
|
+
return _analysis_cache[cache_key]
|
|
11
|
+
|
|
12
|
+
return None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def clear_cache():
|
|
16
|
+
_analysis_cache.clear()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class DocsIndex:
|
|
5
|
+
|
|
6
|
+
def __init__(self, docs_path: str | None = None):
|
|
7
|
+
if docs_path:
|
|
8
|
+
self.docs_path = Path(docs_path)
|
|
9
|
+
else:
|
|
10
|
+
self.docs_path = Path(__file__).parent.parent.parent.parent.parent / \
|
|
11
|
+
"curriculum" / "cutlass-docs" / "cutedsl-docs"
|
|
12
|
+
|
|
13
|
+
self.index = self._build_index()
|
|
14
|
+
|
|
15
|
+
def _build_index(self) -> dict[str, list[str]]:
|
|
16
|
+
return {
|
|
17
|
+
"layout": [
|
|
18
|
+
"intro-to-cutedsl.md",
|
|
19
|
+
"partitioning-strategies-inner-outer-threadvalue.md"
|
|
20
|
+
],
|
|
21
|
+
"TMA": ["blackwell-tutorial-fp16-gemm-0.md"],
|
|
22
|
+
"TMEM": ["colfax-blackwell-umma-tensor-memory-part1.md"],
|
|
23
|
+
"kernel": ["blackwell-tutorial-fp16-gemm-0.md"],
|
|
24
|
+
"struct": ["blackwell-tutorial-fp16-gemm-0.md"],
|
|
25
|
+
"pipeline": ["blackwell-tutorial-fp16-gemm-0.md"],
|
|
26
|
+
"MMA": ["mma-atoms-fundamentals-sm70-example.md"],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def get_doc_for_concept(self, concept: str) -> str | None:
|
|
30
|
+
concept_lower = concept.lower()
|
|
31
|
+
if self.index.get(concept_lower):
|
|
32
|
+
doc_file = self.index[concept_lower][0]
|
|
33
|
+
doc_path = self.docs_path / doc_file
|
|
34
|
+
if doc_path.exists():
|
|
35
|
+
return str(doc_path)
|
|
36
|
+
return None
|
|
File without changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
from lsprotocol.types import CodeAction, CodeActionKind, Command, Range
|
|
3
|
+
|
|
4
|
+
from ..languages.registry import get_language_registry
|
|
5
|
+
from ..languages.types import KernelInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def find_kernel_at_range(content: str, range: Range, uri: str) -> KernelInfo | None:
|
|
9
|
+
registry = get_language_registry()
|
|
10
|
+
language_info = registry.parse_file(uri, content)
|
|
11
|
+
|
|
12
|
+
if not language_info:
|
|
13
|
+
return None
|
|
14
|
+
|
|
15
|
+
for kernel in language_info.kernels:
|
|
16
|
+
if kernel.line <= range.start.line <= kernel.line + 50:
|
|
17
|
+
return kernel
|
|
18
|
+
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def handle_code_action(uri: str, range: Range, content: str) -> list[CodeAction]:
|
|
23
|
+
kernel = find_kernel_at_range(content, range, uri)
|
|
24
|
+
if not kernel:
|
|
25
|
+
return []
|
|
26
|
+
|
|
27
|
+
actions: list[CodeAction] = [
|
|
28
|
+
CodeAction(
|
|
29
|
+
title=f"Analyze Kernel: {kernel.name}",
|
|
30
|
+
kind=CodeActionKind.Source,
|
|
31
|
+
command=Command(
|
|
32
|
+
title=f"Analyze Kernel: {kernel.name}",
|
|
33
|
+
command="wafer.analyzeKernel",
|
|
34
|
+
arguments=[uri, kernel.name]
|
|
35
|
+
)
|
|
36
|
+
),
|
|
37
|
+
CodeAction(
|
|
38
|
+
title=f"Profile Kernel: {kernel.name}",
|
|
39
|
+
kind=CodeActionKind.Source,
|
|
40
|
+
command=Command(
|
|
41
|
+
title=f"Profile Kernel: {kernel.name}",
|
|
42
|
+
command="wafer.profileKernel",
|
|
43
|
+
arguments=[uri, kernel.name]
|
|
44
|
+
)
|
|
45
|
+
),
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
return actions
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
from lsprotocol.types import CodeLens, Command, Position, Range
|
|
3
|
+
|
|
4
|
+
from ..languages.registry import get_language_registry
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def handle_code_lens(uri: str, content: str) -> list[CodeLens]:
|
|
8
|
+
registry = get_language_registry()
|
|
9
|
+
language_info = registry.parse_file(uri, content)
|
|
10
|
+
|
|
11
|
+
if not language_info:
|
|
12
|
+
return []
|
|
13
|
+
|
|
14
|
+
lenses: list[CodeLens] = []
|
|
15
|
+
|
|
16
|
+
for kernel in language_info.kernels:
|
|
17
|
+
lens_range = Range(
|
|
18
|
+
start=Position(line=kernel.line, character=0),
|
|
19
|
+
end=Position(line=kernel.line, character=0)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
analyze_command = Command(
|
|
23
|
+
title=f"Analyze {kernel.name}",
|
|
24
|
+
command="wafer.analyzeKernel",
|
|
25
|
+
arguments=[uri, kernel.name]
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
profile_command = Command(
|
|
29
|
+
title=f"Profile {kernel.name}",
|
|
30
|
+
command="wafer.profileKernel",
|
|
31
|
+
arguments=[uri, kernel.name]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
lenses.append(CodeLens(
|
|
35
|
+
range=lens_range,
|
|
36
|
+
command=analyze_command
|
|
37
|
+
))
|
|
38
|
+
|
|
39
|
+
profile_range = Range(
|
|
40
|
+
start=Position(line=kernel.line, character=20),
|
|
41
|
+
end=Position(line=kernel.line, character=20)
|
|
42
|
+
)
|
|
43
|
+
lenses.append(CodeLens(
|
|
44
|
+
range=profile_range,
|
|
45
|
+
command=profile_command
|
|
46
|
+
))
|
|
47
|
+
|
|
48
|
+
return lenses
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
from lsprotocol.types import Diagnostic
|
|
3
|
+
|
|
4
|
+
from ..languages.registry import get_language_registry
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def handle_diagnostics(uri: str, content: str) -> list[Diagnostic]:
|
|
8
|
+
diagnostics: list[Diagnostic] = []
|
|
9
|
+
|
|
10
|
+
registry = get_language_registry()
|
|
11
|
+
language_info = registry.parse_file(uri, content)
|
|
12
|
+
|
|
13
|
+
if not language_info:
|
|
14
|
+
return diagnostics
|
|
15
|
+
|
|
16
|
+
return diagnostics
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
|
|
2
|
+
from lsprotocol.types import DocumentSymbol, Position, Range, SymbolKind
|
|
3
|
+
|
|
4
|
+
from ..languages.registry import get_language_registry
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def handle_document_symbol(uri: str, content: str) -> list[DocumentSymbol]:
|
|
8
|
+
registry = get_language_registry()
|
|
9
|
+
language_info = registry.parse_file(uri, content)
|
|
10
|
+
|
|
11
|
+
if not language_info:
|
|
12
|
+
return []
|
|
13
|
+
|
|
14
|
+
symbols: list[DocumentSymbol] = []
|
|
15
|
+
|
|
16
|
+
for kernel in language_info.kernels:
|
|
17
|
+
lines = content.split("\n")
|
|
18
|
+
kernel_line = lines[kernel.line] if kernel.line < len(lines) else ""
|
|
19
|
+
name_start = kernel_line.find(kernel.name)
|
|
20
|
+
name_end = name_start + len(kernel.name) if name_start >= 0 else 0
|
|
21
|
+
|
|
22
|
+
selection_range = Range(
|
|
23
|
+
start=Position(line=kernel.line, character=max(0, name_start)),
|
|
24
|
+
end=Position(line=kernel.line, character=name_end)
|
|
25
|
+
)
|
|
26
|
+
full_range = Range(
|
|
27
|
+
start=Position(line=kernel.line, character=0),
|
|
28
|
+
end=Position(line=min(kernel.line + 10, len(lines) - 1), character=0)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
symbols.append(DocumentSymbol(
|
|
32
|
+
name=kernel.name,
|
|
33
|
+
kind=SymbolKind.Function,
|
|
34
|
+
range=full_range,
|
|
35
|
+
selection_range=selection_range,
|
|
36
|
+
detail=f"GPU Kernel ({registry.get_language_name(kernel.language)})",
|
|
37
|
+
))
|
|
38
|
+
|
|
39
|
+
for layout in language_info.layouts:
|
|
40
|
+
lines = content.split("\n")
|
|
41
|
+
layout_line = lines[layout.line] if layout.line < len(lines) else ""
|
|
42
|
+
name_start = layout_line.find(layout.name)
|
|
43
|
+
name_end = name_start + len(layout.name) if name_start >= 0 else 0
|
|
44
|
+
|
|
45
|
+
detail = f"Layout: {layout.shape}" if layout.shape else "Layout"
|
|
46
|
+
|
|
47
|
+
selection_range = Range(
|
|
48
|
+
start=Position(line=layout.line, character=max(0, name_start)),
|
|
49
|
+
end=Position(line=layout.line, character=name_end)
|
|
50
|
+
)
|
|
51
|
+
full_range = Range(
|
|
52
|
+
start=Position(line=layout.line, character=0),
|
|
53
|
+
end=Position(line=layout.line, character=len(layout_line))
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
symbols.append(DocumentSymbol(
|
|
57
|
+
name=layout.name,
|
|
58
|
+
kind=SymbolKind.Variable,
|
|
59
|
+
range=full_range,
|
|
60
|
+
selection_range=selection_range,
|
|
61
|
+
detail=detail,
|
|
62
|
+
))
|
|
63
|
+
|
|
64
|
+
for struct in language_info.structs:
|
|
65
|
+
lines = content.split("\n")
|
|
66
|
+
struct_line = lines[struct.line] if struct.line < len(lines) else ""
|
|
67
|
+
name_start = struct_line.find(struct.name)
|
|
68
|
+
name_end = name_start + len(struct.name) if name_start >= 0 else 0
|
|
69
|
+
|
|
70
|
+
selection_range = Range(
|
|
71
|
+
start=Position(line=struct.line, character=max(0, name_start)),
|
|
72
|
+
end=Position(line=struct.line, character=name_end)
|
|
73
|
+
)
|
|
74
|
+
full_range = Range(
|
|
75
|
+
start=Position(line=struct.line, character=0),
|
|
76
|
+
end=Position(line=min(struct.line + 10, len(lines) - 1), character=0)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
symbols.append(DocumentSymbol(
|
|
80
|
+
name=struct.name,
|
|
81
|
+
kind=SymbolKind.Struct,
|
|
82
|
+
range=full_range,
|
|
83
|
+
selection_range=selection_range,
|
|
84
|
+
detail=f"Struct ({registry.get_language_name(struct.language)})",
|
|
85
|
+
))
|
|
86
|
+
|
|
87
|
+
return symbols
|