wafer-lsp 0.1.0__tar.gz → 0.1.2__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.
Files changed (64) hide show
  1. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/.gitignore +34 -1
  2. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/PKG-INFO +4 -1
  3. wafer_lsp-0.1.2/pyproject.toml +73 -0
  4. wafer_lsp-0.1.0/pyproject.toml → wafer_lsp-0.1.2/pyproject.toml.bak +7 -1
  5. wafer_lsp-0.1.2/src/wafer_lsp/handlers/__init__.py +30 -0
  6. wafer_lsp-0.1.2/src/wafer_lsp/handlers/diagnostics.py +41 -0
  7. wafer_lsp-0.1.2/src/wafer_lsp/handlers/document_symbol.py +176 -0
  8. wafer_lsp-0.1.2/src/wafer_lsp/handlers/hip_diagnostics.py +303 -0
  9. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/handlers/hover.py +45 -9
  10. wafer_lsp-0.1.2/src/wafer_lsp/handlers/inlay_hint.py +245 -0
  11. wafer_lsp-0.1.2/src/wafer_lsp/handlers/semantic_tokens.py +224 -0
  12. wafer_lsp-0.1.2/src/wafer_lsp/languages/detector.py +107 -0
  13. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/languages/registry.py +22 -1
  14. wafer_lsp-0.1.2/src/wafer_lsp/parsers/__init__.py +36 -0
  15. wafer_lsp-0.1.2/src/wafer_lsp/parsers/hip_parser.py +688 -0
  16. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/services/__init__.py +17 -0
  17. wafer_lsp-0.1.2/src/wafer_lsp/services/hip_docs.py +806 -0
  18. wafer_lsp-0.1.2/src/wafer_lsp/services/hip_hover_service.py +412 -0
  19. wafer_lsp-0.1.2/tests/fixtures/example.hip +265 -0
  20. wafer_lsp-0.1.2/tests/test_hip_diagnostics.py +335 -0
  21. wafer_lsp-0.1.2/tests/test_hip_hover.py +374 -0
  22. wafer_lsp-0.1.2/tests/test_hip_parser.py +384 -0
  23. wafer_lsp-0.1.2/tests/test_lsp_e2e.py +591 -0
  24. wafer_lsp-0.1.2/uv.lock +1732 -0
  25. wafer_lsp-0.1.0/src/wafer_lsp/handlers/diagnostics.py +0 -16
  26. wafer_lsp-0.1.0/src/wafer_lsp/handlers/document_symbol.py +0 -87
  27. wafer_lsp-0.1.0/src/wafer_lsp/handlers/inlay_hint.py +0 -65
  28. wafer_lsp-0.1.0/src/wafer_lsp/handlers/semantic_tokens.py +0 -124
  29. wafer_lsp-0.1.0/src/wafer_lsp/languages/detector.py +0 -34
  30. wafer_lsp-0.1.0/src/wafer_lsp/parsers/__init__.py +0 -18
  31. wafer_lsp-0.1.0/src/wafer_lsp/utils/__init__.py +0 -0
  32. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/README.md +0 -0
  33. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/__init__.py +0 -0
  34. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/__main__.py +0 -0
  35. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/analyzers/__init__.py +0 -0
  36. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/analyzers/compiler_integration.py +0 -0
  37. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/analyzers/docs_index.py +0 -0
  38. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/handlers/code_action.py +0 -0
  39. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/handlers/code_lens.py +0 -0
  40. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/handlers/completion.py +0 -0
  41. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/handlers/workspace_symbol.py +0 -0
  42. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/languages/README.md +0 -0
  43. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/languages/__init__.py +0 -0
  44. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/languages/converter.py +0 -0
  45. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/languages/parser_manager.py +0 -0
  46. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/languages/types.py +0 -0
  47. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/parsers/base_parser.py +0 -0
  48. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/parsers/cuda_parser.py +0 -0
  49. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/parsers/cutedsl_parser.py +0 -0
  50. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/server.py +0 -0
  51. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/services/analysis_service.py +0 -0
  52. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/services/docs_service.py +0 -0
  53. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/services/document_service.py +0 -0
  54. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/services/hover_service.py +0 -0
  55. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/services/language_registry_service.py +0 -0
  56. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/services/position_service.py +0 -0
  57. {wafer_lsp-0.1.0/src/wafer_lsp/handlers → wafer_lsp-0.1.2/src/wafer_lsp/utils}/__init__.py +0 -0
  58. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/src/wafer_lsp/utils/lsp_helpers.py +0 -0
  59. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/tests/__init__.py +0 -0
  60. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/tests/test_converter.py +0 -0
  61. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/tests/test_cutedsl_parser.py +0 -0
  62. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/tests/test_language_detector.py +0 -0
  63. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/tests/test_lsp_handlers.py +0 -0
  64. {wafer_lsp-0.1.0 → wafer_lsp-0.1.2}/tests/test_parser_manager.py +0 -0
@@ -40,6 +40,12 @@ experiments/emilio/cutedsl-quack-eval/eval_results/*.txt
40
40
  experiments/emilio/cutedsl-quack-eval/eval_results/*.json
41
41
  experiments/emilio/cutedsl-quack-eval/eval_results/*.py
42
42
  research/evals/kernelbench/results/
43
+ research/evals/retrieval_eval_project/results/
44
+ research/evals/trace_analyze_eval/results/
45
+ research/evals/**/uv.lock
46
+
47
+ # Large trace files
48
+ **/pmc_perf.csv
43
49
  wafer_artifacts/
44
50
  **/wafer_artifacts/
45
51
  /.deps/
@@ -61,11 +67,14 @@ npm-debug.log*
61
67
  .npmrc
62
68
 
63
69
  # Yarn artifacts
64
- .yarn/install-state.gz
70
+ **/.yarn/install-state.gz
65
71
 
66
72
  # NSYS report files (can be very large)
67
73
  *.nsys-rep
68
74
 
75
+ # ROCprofiler artifacts
76
+ .rocprofv3/
77
+
69
78
  # Turbo build cache
70
79
  .turbo/
71
80
  **/.turbo/
@@ -80,6 +89,30 @@ supabase/.temp/
80
89
  research/evals/kernelbench/kernelbench/results/
81
90
  research/evals/retrieval_eval_project/retrieval_eval/results/
82
91
  research/evals/retrieval_eval_project/*.log
92
+ research/evals/ask_domain_eval/results/
93
+ research/evals/optimize_performance_eval/results/
94
+ research/evals/**/eval_output*.log
83
95
 
84
96
  # Wafer extension trace files
85
97
  .wafer/traces/
98
+
99
+ # Test coverage
100
+ coverage/
101
+ **/coverage/
102
+ .coverage
103
+ *.coverage
104
+ coverage.xml
105
+ *.lcov
106
+ htmlcov/
107
+ experiments/steve/amd-model-practice/workloads/**/*.csv
108
+ experiments/steve/amd-model-practice/liquid_profile.json
109
+
110
+ # Local files
111
+ logs/
112
+ todo.md
113
+
114
+ # Claude Code context/handoffs
115
+ .claude/context/
116
+ .claude/handoffs/
117
+ KernelBench/
118
+ HIP-Benchmarks-Results/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wafer-lsp
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Language Server Protocol server for GPU programming languages
5
5
  Author-email: Wafer <support@wafer.ai>
6
6
  License: MIT
@@ -16,6 +16,9 @@ Requires-Python: >=3.12
16
16
  Requires-Dist: lsprotocol>=2024.0.0
17
17
  Requires-Dist: pygls>=1.0.0
18
18
  Requires-Dist: wafer-core
19
+ Provides-Extra: dev
20
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
21
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
19
22
  Description-Content-Type: text/markdown
20
23
 
21
24
  # Wafer LSP
@@ -0,0 +1,73 @@
1
+ [project]
2
+ name = "wafer-lsp"
3
+ version = "0.1.2"
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 core analysis utilities
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
+ [project.optional-dependencies]
28
+ dev = [
29
+ "pytest>=8.0.0",
30
+ "pytest-asyncio>=0.23.0",
31
+ ]
32
+
33
+ [build-system]
34
+ requires = ["hatchling"]
35
+ build-backend = "hatchling.build"
36
+
37
+ [project.scripts]
38
+ wafer-lsp = "wafer_lsp.__main__:main"
39
+
40
+ [tool.hatch.build.targets.wheel]
41
+ packages = ["src/wafer_lsp"]
42
+
43
+ [tool.ruff]
44
+ line-length = 100
45
+ target-version = "py312"
46
+ preview = true
47
+
48
+ [tool.ruff.lint]
49
+ select = [
50
+ "E", # pycodestyle errors
51
+ "W", # pycodestyle warnings
52
+ "F", # pyflakes
53
+ "I", # isort
54
+ "B", # flake8-bugbear
55
+ "C4", # flake8-comprehensions
56
+ "UP", # pyupgrade
57
+ "ARG", # flake8-unused-arguments
58
+ "SIM", # flake8-simplify
59
+ "PLR", # pylint refactor
60
+ "PLW", # pylint warnings
61
+ "PT", # flake8-pytest-style
62
+ "RUF", # Ruff-specific rules
63
+ ]
64
+ ignore = [
65
+ "E501", # line too long (handled by formatter)
66
+ "B008", # do not perform function calls in argument defaults
67
+ "PLR0913", # too many arguments
68
+ "PLR2004", # magic value used in comparison
69
+ ]
70
+
71
+ [tool.ruff.format]
72
+ quote-style = "double"
73
+ indent-style = "space"
@@ -7,7 +7,7 @@ requires-python = ">=3.12"
7
7
  dependencies = [
8
8
  "pygls>=1.0.0",
9
9
  "lsprotocol>=2024.0.0",
10
- "wafer-core", # For compiler analyzer
10
+ "wafer-core", # For core analysis utilities
11
11
  ]
12
12
  authors = [
13
13
  { name = "Wafer", email = "support@wafer.ai" }
@@ -24,6 +24,12 @@ classifiers = [
24
24
  "Topic :: Text Editors :: Integrated Development Environments (IDE)",
25
25
  ]
26
26
 
27
+ [project.optional-dependencies]
28
+ dev = [
29
+ "pytest>=8.0.0",
30
+ "pytest-asyncio>=0.23.0",
31
+ ]
32
+
27
33
  [build-system]
28
34
  requires = ["hatchling"]
29
35
  build-backend = "hatchling.build"
@@ -0,0 +1,30 @@
1
+ from .code_action import handle_code_action
2
+ from .code_lens import handle_code_lens
3
+ from .completion import handle_completion
4
+ from .diagnostics import handle_diagnostics
5
+ from .document_symbol import handle_document_symbol
6
+ from .hip_diagnostics import (
7
+ HIPDiagnosticsProvider,
8
+ create_hip_diagnostics_provider,
9
+ get_hip_diagnostics,
10
+ )
11
+ from .hover import handle_hover
12
+ from .inlay_hint import handle_inlay_hint
13
+ from .semantic_tokens import handle_semantic_tokens, SEMANTIC_TOKENS_LEGEND
14
+ from .workspace_symbol import handle_workspace_symbol
15
+
16
+ __all__ = [
17
+ "handle_code_action",
18
+ "handle_code_lens",
19
+ "handle_completion",
20
+ "handle_diagnostics",
21
+ "handle_document_symbol",
22
+ "handle_hover",
23
+ "handle_inlay_hint",
24
+ "handle_semantic_tokens",
25
+ "handle_workspace_symbol",
26
+ "SEMANTIC_TOKENS_LEGEND",
27
+ "HIPDiagnosticsProvider",
28
+ "create_hip_diagnostics_provider",
29
+ "get_hip_diagnostics",
30
+ ]
@@ -0,0 +1,41 @@
1
+
2
+ from lsprotocol.types import Diagnostic
3
+
4
+ from ..languages.registry import get_language_registry
5
+ from .hip_diagnostics import get_hip_diagnostics
6
+
7
+
8
+ def handle_diagnostics(
9
+ uri: str,
10
+ content: str,
11
+ enable_wavefront_diagnostics: bool = True,
12
+ ) -> list[Diagnostic]:
13
+ """Handle diagnostics for a document.
14
+
15
+ Args:
16
+ uri: Document URI
17
+ content: Document content
18
+ enable_wavefront_diagnostics: Whether to enable HIP wavefront warnings
19
+
20
+ Returns:
21
+ List of diagnostics
22
+ """
23
+ diagnostics: list[Diagnostic] = []
24
+
25
+ registry = get_language_registry()
26
+ language_info = registry.parse_file(uri, content)
27
+
28
+ if not language_info:
29
+ return diagnostics
30
+
31
+ # Add HIP-specific diagnostics for HIP, CUDA, and C++ files
32
+ # (C++ files might contain HIP code if they have HIP markers)
33
+ if language_info.language in ("hip", "cuda", "cpp"):
34
+ hip_diagnostics = get_hip_diagnostics(
35
+ content,
36
+ uri,
37
+ enable_wavefront_diagnostics=enable_wavefront_diagnostics,
38
+ )
39
+ diagnostics.extend(hip_diagnostics)
40
+
41
+ return diagnostics
@@ -0,0 +1,176 @@
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
+ lines = content.split("\n")
16
+
17
+ # Kernels
18
+ for kernel in language_info.kernels:
19
+ kernel_line = lines[kernel.line] if kernel.line < len(lines) else ""
20
+ name_start = kernel_line.find(kernel.name)
21
+ name_end = name_start + len(kernel.name) if name_start >= 0 else 0
22
+
23
+ selection_range = Range(
24
+ start=Position(line=kernel.line, character=max(0, name_start)),
25
+ end=Position(line=kernel.line, character=name_end)
26
+ )
27
+ full_range = Range(
28
+ start=Position(line=kernel.line, character=0),
29
+ end=Position(line=min(kernel.line + 10, len(lines) - 1), character=0)
30
+ )
31
+
32
+ # Different detail based on language
33
+ if kernel.language == "hip":
34
+ detail = "🚀 HIP Kernel (AMD GPU)"
35
+ elif kernel.language in ("cuda", "cpp"):
36
+ detail = "🚀 CUDA Kernel"
37
+ else:
38
+ detail = f"GPU Kernel ({registry.get_language_name(kernel.language)})"
39
+
40
+ symbols.append(DocumentSymbol(
41
+ name=kernel.name,
42
+ kind=SymbolKind.Function,
43
+ range=full_range,
44
+ selection_range=selection_range,
45
+ detail=detail,
46
+ ))
47
+
48
+ # Layouts (CuTeDSL)
49
+ for layout in language_info.layouts:
50
+ layout_line = lines[layout.line] if layout.line < len(lines) else ""
51
+ name_start = layout_line.find(layout.name)
52
+ name_end = name_start + len(layout.name) if name_start >= 0 else 0
53
+
54
+ detail = f"Layout: {layout.shape}" if layout.shape else "Layout"
55
+
56
+ selection_range = Range(
57
+ start=Position(line=layout.line, character=max(0, name_start)),
58
+ end=Position(line=layout.line, character=name_end)
59
+ )
60
+ full_range = Range(
61
+ start=Position(line=layout.line, character=0),
62
+ end=Position(line=layout.line, character=len(layout_line))
63
+ )
64
+
65
+ symbols.append(DocumentSymbol(
66
+ name=layout.name,
67
+ kind=SymbolKind.Variable,
68
+ range=full_range,
69
+ selection_range=selection_range,
70
+ detail=detail,
71
+ ))
72
+
73
+ # Structs
74
+ for struct in language_info.structs:
75
+ struct_line = lines[struct.line] if struct.line < len(lines) else ""
76
+ name_start = struct_line.find(struct.name)
77
+ name_end = name_start + len(struct.name) if name_start >= 0 else 0
78
+
79
+ selection_range = Range(
80
+ start=Position(line=struct.line, character=max(0, name_start)),
81
+ end=Position(line=struct.line, character=name_end)
82
+ )
83
+ full_range = Range(
84
+ start=Position(line=struct.line, character=0),
85
+ end=Position(line=min(struct.line + 10, len(lines) - 1), character=0)
86
+ )
87
+
88
+ symbols.append(DocumentSymbol(
89
+ name=struct.name,
90
+ kind=SymbolKind.Struct,
91
+ range=full_range,
92
+ selection_range=selection_range,
93
+ detail=f"Struct ({registry.get_language_name(struct.language)})",
94
+ ))
95
+
96
+ # HIP-specific: Device functions and shared memory
97
+ if language_info.language in ("hip", "cuda", "cpp"):
98
+ symbols.extend(_get_hip_symbols(language_info.raw_data, lines))
99
+
100
+ return symbols
101
+
102
+
103
+ def _get_hip_symbols(raw_data: dict, lines: list[str]) -> list[DocumentSymbol]:
104
+ """Extract HIP-specific symbols: device functions, shared memory allocations."""
105
+ symbols: list[DocumentSymbol] = []
106
+
107
+ # Device functions (from HIP parser)
108
+ device_functions = raw_data.get("device_functions", [])
109
+ for func in device_functions:
110
+ if not hasattr(func, "line") or not hasattr(func, "name"):
111
+ continue
112
+
113
+ func_line = lines[func.line] if func.line < len(lines) else ""
114
+ name_start = func_line.find(func.name)
115
+ name_end = name_start + len(func.name) if name_start >= 0 else 0
116
+
117
+ end_line = getattr(func, "end_line", func.line + 10)
118
+
119
+ selection_range = Range(
120
+ start=Position(line=func.line, character=max(0, name_start)),
121
+ end=Position(line=func.line, character=name_end)
122
+ )
123
+ full_range = Range(
124
+ start=Position(line=func.line, character=0),
125
+ end=Position(line=min(end_line, len(lines) - 1), character=0)
126
+ )
127
+
128
+ return_type = getattr(func, "return_type", "void")
129
+ detail = f"⚡ Device Function -> {return_type}"
130
+
131
+ symbols.append(DocumentSymbol(
132
+ name=func.name,
133
+ kind=SymbolKind.Method,
134
+ range=full_range,
135
+ selection_range=selection_range,
136
+ detail=detail,
137
+ ))
138
+
139
+ # Shared memory allocations
140
+ shared_memory = raw_data.get("shared_memory", [])
141
+ for shared in shared_memory:
142
+ if not hasattr(shared, "line") or not hasattr(shared, "name"):
143
+ continue
144
+
145
+ shared_line = lines[shared.line] if shared.line < len(lines) else ""
146
+ name_start = shared_line.find(shared.name)
147
+ name_end = name_start + len(shared.name) if name_start >= 0 else 0
148
+
149
+ selection_range = Range(
150
+ start=Position(line=shared.line, character=max(0, name_start)),
151
+ end=Position(line=shared.line, character=name_end)
152
+ )
153
+ full_range = Range(
154
+ start=Position(line=shared.line, character=0),
155
+ end=Position(line=shared.line, character=len(shared_line))
156
+ )
157
+
158
+ type_str = getattr(shared, "type_str", "")
159
+ size_bytes = getattr(shared, "size_bytes", None)
160
+ if size_bytes:
161
+ if size_bytes >= 1024:
162
+ detail = f"📦 __shared__ {type_str} ({size_bytes / 1024:.1f} KB)"
163
+ else:
164
+ detail = f"📦 __shared__ {type_str} ({size_bytes} bytes)"
165
+ else:
166
+ detail = f"📦 __shared__ {type_str}"
167
+
168
+ symbols.append(DocumentSymbol(
169
+ name=shared.name,
170
+ kind=SymbolKind.Variable,
171
+ range=full_range,
172
+ selection_range=selection_range,
173
+ detail=detail,
174
+ ))
175
+
176
+ return symbols