pyxle-langkit 0.2.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.
Files changed (51) hide show
  1. pyxle_langkit-0.2.0/.gitignore +32 -0
  2. pyxle_langkit-0.2.0/CLAUDE.md +163 -0
  3. pyxle_langkit-0.2.0/LICENSE +21 -0
  4. pyxle_langkit-0.2.0/PKG-INFO +69 -0
  5. pyxle_langkit-0.2.0/README.md +35 -0
  6. pyxle_langkit-0.2.0/editors/vscode/.vscodeignore +10 -0
  7. pyxle_langkit-0.2.0/editors/vscode/LICENSE +21 -0
  8. pyxle_langkit-0.2.0/editors/vscode/icons/pyx.svg +11 -0
  9. pyxle_langkit-0.2.0/editors/vscode/language-configuration.json +51 -0
  10. pyxle_langkit-0.2.0/editors/vscode/package.json +106 -0
  11. pyxle_langkit-0.2.0/editors/vscode/src/extension.ts +135 -0
  12. pyxle_langkit-0.2.0/editors/vscode/src/status.ts +59 -0
  13. pyxle_langkit-0.2.0/editors/vscode/syntaxes/pyx.tmLanguage.json +27 -0
  14. pyxle_langkit-0.2.0/editors/vscode/tsconfig.json +20 -0
  15. pyxle_langkit-0.2.0/package.json +8 -0
  16. pyxle_langkit-0.2.0/pyproject.toml +71 -0
  17. pyxle_langkit-0.2.0/pyxle_langkit/__init__.py +18 -0
  18. pyxle_langkit-0.2.0/pyxle_langkit/cli.py +206 -0
  19. pyxle_langkit-0.2.0/pyxle_langkit/completions.py +397 -0
  20. pyxle_langkit-0.2.0/pyxle_langkit/definitions.py +273 -0
  21. pyxle_langkit-0.2.0/pyxle_langkit/diagnostics.py +142 -0
  22. pyxle_langkit-0.2.0/pyxle_langkit/document.py +187 -0
  23. pyxle_langkit-0.2.0/pyxle_langkit/formatting.py +292 -0
  24. pyxle_langkit-0.2.0/pyxle_langkit/hover.py +407 -0
  25. pyxle_langkit-0.2.0/pyxle_langkit/js/jsx_component_extractor.mjs +193 -0
  26. pyxle_langkit-0.2.0/pyxle_langkit/js/react_parser_runner.mjs +116 -0
  27. pyxle_langkit-0.2.0/pyxle_langkit/js/ts_service.mjs +338 -0
  28. pyxle_langkit-0.2.0/pyxle_langkit/linter.py +850 -0
  29. pyxle_langkit-0.2.0/pyxle_langkit/parser_adapter.py +123 -0
  30. pyxle_langkit-0.2.0/pyxle_langkit/react_checker.py +248 -0
  31. pyxle_langkit-0.2.0/pyxle_langkit/semantic_tokens.py +363 -0
  32. pyxle_langkit-0.2.0/pyxle_langkit/server.py +639 -0
  33. pyxle_langkit-0.2.0/pyxle_langkit/symbols.py +253 -0
  34. pyxle_langkit-0.2.0/pyxle_langkit/ts_bridge.py +319 -0
  35. pyxle_langkit-0.2.0/pyxle_langkit/workspace.py +193 -0
  36. pyxle_langkit-0.2.0/tests/__init__.py +0 -0
  37. pyxle_langkit-0.2.0/tests/conftest.py +123 -0
  38. pyxle_langkit-0.2.0/tests/test_cli.py +318 -0
  39. pyxle_langkit-0.2.0/tests/test_completions.py +447 -0
  40. pyxle_langkit-0.2.0/tests/test_definitions.py +491 -0
  41. pyxle_langkit-0.2.0/tests/test_diagnostics.py +224 -0
  42. pyxle_langkit-0.2.0/tests/test_document.py +258 -0
  43. pyxle_langkit-0.2.0/tests/test_formatting.py +460 -0
  44. pyxle_langkit-0.2.0/tests/test_hover.py +464 -0
  45. pyxle_langkit-0.2.0/tests/test_linter.py +1879 -0
  46. pyxle_langkit-0.2.0/tests/test_parser_adapter.py +219 -0
  47. pyxle_langkit-0.2.0/tests/test_react_checker.py +311 -0
  48. pyxle_langkit-0.2.0/tests/test_semantic_tokens.py +439 -0
  49. pyxle_langkit-0.2.0/tests/test_server.py +1184 -0
  50. pyxle_langkit-0.2.0/tests/test_symbols.py +366 -0
  51. pyxle_langkit-0.2.0/tests/test_workspace.py +259 -0
@@ -0,0 +1,32 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[codz]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+
9
+ # Coverage
10
+ .coverage
11
+ htmlcov/
12
+ .pytest_cache/
13
+
14
+ # Node
15
+ node_modules/
16
+ package-lock.json
17
+
18
+ # VS Code extension build
19
+ editors/vscode/out/
20
+ editors/vscode/node_modules/
21
+ editors/vscode/*.vsix
22
+
23
+ # Ruff
24
+ .ruff_cache/
25
+
26
+ # IDE
27
+ .vscode/
28
+ .idea/
29
+
30
+ # OS
31
+ .DS_Store
32
+ Thumbs.db
@@ -0,0 +1,163 @@
1
+ # CLAUDE.md — Pyxle Langkit v2
2
+
3
+ Language tooling suite for Pyxle — powers IDE support for `.pyx` files.
4
+
5
+ ---
6
+
7
+ ## Project Overview
8
+
9
+ Pyxle Langkit provides IDE support for `.pyx` files — the hybrid Python/JSX format
10
+ used by the Pyxle framework. The architecture is **server-driven**: all intelligence
11
+ lives in the Python LSP server, and the VS Code extension is a thin LSP client.
12
+
13
+ **Key architecture decisions:**
14
+ - **jedi** for Python completions, definitions, hover, references
15
+ - **pyflakes** for Python static analysis
16
+ - **Babel** (Node.js subprocess) for JSX validation
17
+ - **pygls** for the LSP server framework
18
+ - **TypeScript** for the VS Code extension
19
+ - **No virtual files on disk** — jedi analyzes in-memory, no SegmentManager
20
+
21
+ ---
22
+
23
+ ## Module Map
24
+
25
+ ```
26
+ pyxle_langkit/
27
+ |-- __init__.py # Public API exports
28
+ |-- server.py # PyxleLanguageServer (pygls) — main LSP orchestrator
29
+ |-- parser_adapter.py # Tolerant parser wrapper (never raises)
30
+ |-- document.py # PyxDocument — parsed .pyx with line mapping
31
+ |-- workspace.py # WorkspaceIndex — tracks all .pyx files
32
+ |-- linter.py # Static analysis: pyflakes, Pyxle rules, React rules
33
+ |-- react_checker.py # Babel-based JSX validation via Node.js
34
+ |-- completions.py # jedi + Pyxle-specific completions
35
+ |-- hover.py # jedi + Pyxle-specific hover docs
36
+ |-- definitions.py # jedi + cross-section go-to-definition
37
+ |-- diagnostics.py # Diagnostic aggregation + position mapping
38
+ |-- symbols.py # Document + workspace symbols
39
+ |-- formatting.py # ruff (Python) + prettier (JSX) coordinator
40
+ |-- semantic_tokens.py # AST-based semantic tokens
41
+ |-- cli.py # CLI: parse, lint, outline, format
42
+ +-- js/ # Node.js helpers
43
+ |-- react_parser_runner.mjs
44
+ +-- jsx_component_extractor.mjs
45
+
46
+ editors/vscode/ # VS Code extension (TypeScript, thin client)
47
+ |-- src/
48
+ | |-- extension.ts # Activation + LSP client lifecycle
49
+ | +-- status.ts # Status bar management
50
+ |-- syntaxes/
51
+ | +-- pyx.tmLanguage.json
52
+ |-- test/
53
+ | |-- suite/
54
+ | | +-- extension.test.ts
55
+ | +-- runTest.ts
56
+ |-- package.json
57
+ |-- tsconfig.json
58
+ +-- language-configuration.json
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Setup
64
+
65
+ ```bash
66
+ # Install core framework (editable)
67
+ pip install -e /path/to/pyxle[dev]
68
+
69
+ # Install langkit
70
+ pip install -e .[dev]
71
+
72
+ # Install Babel helpers
73
+ npm install
74
+
75
+ # Build VS Code extension
76
+ cd editors/vscode && npm install && npm run compile
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Mandatory Rules
82
+
83
+ ### 1. Run Tests After Every Change
84
+
85
+ ```bash
86
+ pytest # Full suite with coverage
87
+ pytest tests/ -x # Stop on first failure
88
+ pytest --no-cov # Skip coverage for faster iteration
89
+ ```
90
+
91
+ All tests must pass. Coverage threshold is 95%.
92
+
93
+ ### 2. Test File Convention
94
+
95
+ ```
96
+ pyxle_langkit/parser_adapter.py -> tests/test_parser_adapter.py
97
+ pyxle_langkit/document.py -> tests/test_document.py
98
+ pyxle_langkit/linter.py -> tests/test_linter.py
99
+ pyxle_langkit/completions.py -> tests/test_completions.py
100
+ pyxle_langkit/hover.py -> tests/test_hover.py
101
+ pyxle_langkit/definitions.py -> tests/test_definitions.py
102
+ pyxle_langkit/server.py -> tests/test_server.py
103
+ pyxle_langkit/workspace.py -> tests/test_workspace.py
104
+ pyxle_langkit/diagnostics.py -> tests/test_diagnostics.py
105
+ pyxle_langkit/symbols.py -> tests/test_symbols.py
106
+ pyxle_langkit/formatting.py -> tests/test_formatting.py
107
+ pyxle_langkit/semantic_tokens.py -> tests/test_semantic_tokens.py
108
+ pyxle_langkit/cli.py -> tests/test_cli.py
109
+ editors/vscode/ -> editors/vscode/test/
110
+ ```
111
+
112
+ ### 3. Lint Before Committing
113
+
114
+ ```bash
115
+ ruff check pyxle_langkit/ tests/
116
+ ```
117
+
118
+ ### 4. Commit Scope Convention
119
+
120
+ Scope examples: `linter`, `server`, `completions`, `hover`, `definitions`,
121
+ `formatting`, `vscode`, `parser`, `cli`, `workspace`.
122
+
123
+ ---
124
+
125
+ ## Module Rules
126
+
127
+ ### Parser Adapter
128
+ - Must tolerate incomplete/malformed code — IDE users type incomplete code constantly
129
+ - Never raise exceptions for parse failures — return PyxDocument with diagnostics
130
+
131
+ ### Linter
132
+ - Python issues use pyflakes — don't reinvent its checks
133
+ - `server` and `action` are whitelisted as globals (injected by Pyxle runtime)
134
+ - JSX issues delegate to Node.js/Babel
135
+ - All issues must have accurate line/column mapped to the original `.pyx` file
136
+
137
+ ### Completions / Hover / Definitions
138
+ - Use jedi for Python intelligence — import safely with try/except
139
+ - If jedi is not available, return Pyxle-specific results only (never crash)
140
+ - Map all positions: .pyx → virtual Python → jedi → virtual Python → .pyx
141
+
142
+ ### LSP Server
143
+ - Never block the event loop with synchronous I/O
144
+ - Use asyncio.to_thread() for jedi calls (jedi is synchronous)
145
+ - Diagnostics published on didOpen, didChange, didSave
146
+
147
+ ### VS Code Extension
148
+ - TypeScript — compiled to out/ directory
149
+ - Thin LSP client only — no SegmentManager, no virtual files
150
+ - All intelligence comes from the LSP server
151
+
152
+ ---
153
+
154
+ ## DO NOT List
155
+
156
+ - **DO NOT** import anything from `pyxle` other than `pyxle.compiler`
157
+ - **DO NOT** add `print()` — use `logging`
158
+ - **DO NOT** write virtual files to disk for language analysis
159
+ - **DO NOT** use mutable dataclasses for data-carrying types
160
+ - **DO NOT** block the async event loop with synchronous I/O
161
+ - **DO NOT** grow caches without eviction policies
162
+ - **DO NOT** hardcode file paths or OS-specific assumptions
163
+ - **DO NOT** commit `.vsix` build artifacts or `node_modules/`
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shivam Saini
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyxle-langkit
3
+ Version: 0.2.0
4
+ Summary: Language tools for Pyxle: LSP server, linter, and editor integrations.
5
+ Project-URL: Homepage, https://pyxle.dev
6
+ Project-URL: Repository, https://github.com/pyxle-framework/pyxle-langkit
7
+ Author-email: Shivam Saini <dev@pyxle.dev>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: language-server,linter,lsp,pyxle,vscode
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Quality Assurance
20
+ Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE)
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: jedi<0.20,>=0.19
24
+ Requires-Dist: lsprotocol>=2023.0.0
25
+ Requires-Dist: pyflakes<3.3,>=3.2
26
+ Requires-Dist: pygls<2.0,>=1.3
27
+ Requires-Dist: pyxle-framework>=0.1.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: coverage<8.0,>=7.4; extra == 'dev'
30
+ Requires-Dist: pytest-cov<5.0,>=4.1; extra == 'dev'
31
+ Requires-Dist: pytest<9.0,>=8.0; extra == 'dev'
32
+ Requires-Dist: ruff<0.7,>=0.6; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # Pyxle Language Toolkit
36
+
37
+ Language tools for [Pyxle](https://pyxle.dev) `.pyx` files — LSP server, linter, and VS Code extension.
38
+
39
+ ## Features
40
+
41
+ - **Syntax highlighting** via TextMate grammar (Python + JSX sections)
42
+ - **Diagnostics** from pyflakes, Babel, and Pyxle-specific rules
43
+ - **Completions** via Jedi (Python) + Pyxle component completions (JSX)
44
+ - **Hover documentation** for Python symbols and Pyxle decorators/components
45
+ - **Go-to-definition** via Jedi with cross-section navigation
46
+ - **Document symbols** and **workspace symbols**
47
+ - **Formatting** with ruff (Python) and prettier (JSX)
48
+ - **Semantic tokens** via AST analysis
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install pyxle-langkit
54
+ ```
55
+
56
+ The VS Code extension is available on the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=pyxle.pyxle-language-tools).
57
+
58
+ ## Architecture
59
+
60
+ All intelligence lives in the Python LSP server. The VS Code extension is a thin LSP client (~100 LOC).
61
+
62
+ - **Python analysis**: [Jedi](https://jedi.readthedocs.io/) for completions, definitions, hover
63
+ - **JSX analysis**: Pyxle-specific completions + [Babel](https://babeljs.io/) for validation
64
+ - **Static analysis**: [pyflakes](https://pypi.org/project/pyflakes/) + Pyxle rules
65
+ - **LSP framework**: [pygls](https://pygls.readthedocs.io/)
66
+
67
+ ## License
68
+
69
+ MIT
@@ -0,0 +1,35 @@
1
+ # Pyxle Language Toolkit
2
+
3
+ Language tools for [Pyxle](https://pyxle.dev) `.pyx` files — LSP server, linter, and VS Code extension.
4
+
5
+ ## Features
6
+
7
+ - **Syntax highlighting** via TextMate grammar (Python + JSX sections)
8
+ - **Diagnostics** from pyflakes, Babel, and Pyxle-specific rules
9
+ - **Completions** via Jedi (Python) + Pyxle component completions (JSX)
10
+ - **Hover documentation** for Python symbols and Pyxle decorators/components
11
+ - **Go-to-definition** via Jedi with cross-section navigation
12
+ - **Document symbols** and **workspace symbols**
13
+ - **Formatting** with ruff (Python) and prettier (JSX)
14
+ - **Semantic tokens** via AST analysis
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install pyxle-langkit
20
+ ```
21
+
22
+ The VS Code extension is available on the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=pyxle.pyxle-language-tools).
23
+
24
+ ## Architecture
25
+
26
+ All intelligence lives in the Python LSP server. The VS Code extension is a thin LSP client (~100 LOC).
27
+
28
+ - **Python analysis**: [Jedi](https://jedi.readthedocs.io/) for completions, definitions, hover
29
+ - **JSX analysis**: Pyxle-specific completions + [Babel](https://babeljs.io/) for validation
30
+ - **Static analysis**: [pyflakes](https://pypi.org/project/pyflakes/) + Pyxle rules
31
+ - **LSP framework**: [pygls](https://pygls.readthedocs.io/)
32
+
33
+ ## License
34
+
35
+ MIT
@@ -0,0 +1,10 @@
1
+ **/*.ts
2
+ !out/**/*.js
3
+ src/**
4
+ test/**
5
+ node_modules/**
6
+ .vscode/**
7
+ .ruff_cache/**
8
+ tsconfig.json
9
+ **/*.map
10
+ **/*.vsix
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shivam Saini
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="g" x1="2" y1="1" x2="14" y2="15" gradientUnits="userSpaceOnUse">
4
+ <stop offset="0" stop-color="#6ee7b7" />
5
+ <stop offset="0.5" stop-color="#34d399" />
6
+ <stop offset="1" stop-color="#059669" />
7
+ </linearGradient>
8
+ </defs>
9
+ <path d="M4.5 13 V3 H9 Q12.5 3 12.5 6.5 Q12.5 10 9 10 H4.5" stroke="url(#g)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none" />
10
+ <circle cx="9" cy="6.5" r="1.2" fill="#6ee7b7" />
11
+ </svg>
@@ -0,0 +1,51 @@
1
+ {
2
+ "comments": {
3
+ "lineComment": "//",
4
+ "blockComment": ["/*", "*/"]
5
+ },
6
+ "brackets": [
7
+ ["{", "}"],
8
+ ["[", "]"],
9
+ ["(", ")"],
10
+ ["<", ">"]
11
+ ],
12
+ "autoClosingPairs": [
13
+ { "open": "{", "close": "}" },
14
+ { "open": "[", "close": "]" },
15
+ { "open": "(", "close": ")" },
16
+ { "open": "'", "close": "'", "notIn": ["string", "comment"] },
17
+ { "open": "\"", "close": "\"", "notIn": ["string", "comment"] },
18
+ { "open": "`", "close": "`", "notIn": ["string", "comment"] },
19
+ { "open": "<", "close": ">", "notIn": ["string", "comment"] }
20
+ ],
21
+ "surroundingPairs": [
22
+ ["{", "}"],
23
+ ["[", "]"],
24
+ ["(", ")"],
25
+ ["'", "'"],
26
+ ["\"", "\""],
27
+ ["`", "`"],
28
+ ["<", ">"]
29
+ ],
30
+ "folding": {
31
+ "markers": {
32
+ "start": "^\\s*(?:#\\s*---\\s*(?:python|server|javascript|client)|(?:def|class|async\\s+def|if|for|while|with|try|export\\s+default\\s+function|function|const)\\b)",
33
+ "end": "^\\s*$"
34
+ }
35
+ },
36
+ "indentationRules": {
37
+ "increaseIndentPattern": "^\\s*(?:def\\b|class\\b|if\\b|elif\\b|else:|for\\b|while\\b|with\\b|try:|except\\b|finally:|async\\s+def\\b|function\\b|=>\\s*\\{|\\{).*$",
38
+ "decreaseIndentPattern": "^\\s*(?:elif\\b|else:|except\\b|finally:|\\}|\\)|\\])"
39
+ },
40
+ "onEnterRules": [
41
+ {
42
+ "beforeText": ":\\s*$",
43
+ "action": { "indent": "indent" }
44
+ },
45
+ {
46
+ "beforeText": "\\{\\s*$",
47
+ "afterText": "^\\s*\\}",
48
+ "action": { "indent": "indent" }
49
+ }
50
+ ]
51
+ }
@@ -0,0 +1,106 @@
1
+ {
2
+ "name": "pyxle-language-tools",
3
+ "displayName": "Pyxle Language Tools",
4
+ "publisher": "pyxle",
5
+ "version": "0.1.0-beta",
6
+ "description": "Language support for Pyxle .pyx files — syntax highlighting, diagnostics, completions, hover, go-to-definition, and formatting.",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/pyxle-framework/pyxle-langkit"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/pyxle-framework/pyxle-langkit/issues"
14
+ },
15
+ "homepage": "https://pyxle.dev",
16
+ "keywords": ["pyxle", "pyx", "python", "react", "jsx", "lsp"],
17
+ "engines": {
18
+ "vscode": "^1.85.0"
19
+ },
20
+ "categories": ["Programming Languages"],
21
+ "activationEvents": ["onLanguage:pyxle"],
22
+ "main": "./out/extension.js",
23
+ "scripts": {
24
+ "compile": "tsc -p ./",
25
+ "watch": "tsc -watch -p ./",
26
+ "lint": "tsc --noEmit",
27
+ "pretest": "npm run compile",
28
+ "test": "node ./out/test/runTest.js",
29
+ "package": "npx @vscode/vsce package --no-dependencies"
30
+ },
31
+ "contributes": {
32
+ "languages": [
33
+ {
34
+ "id": "pyxle",
35
+ "aliases": ["Pyxle", "pyxle"],
36
+ "extensions": [".pyx"],
37
+ "configuration": "./language-configuration.json",
38
+ "icon": {
39
+ "light": "./icons/pyx.svg",
40
+ "dark": "./icons/pyx.svg"
41
+ }
42
+ }
43
+ ],
44
+ "grammars": [
45
+ {
46
+ "language": "pyxle",
47
+ "scopeName": "source.pyxle",
48
+ "path": "./syntaxes/pyx.tmLanguage.json",
49
+ "embeddedLanguages": {
50
+ "source.python": "python",
51
+ "source.js.jsx": "javascriptreact"
52
+ }
53
+ }
54
+ ],
55
+ "configuration": [
56
+ {
57
+ "title": "Pyxle",
58
+ "properties": {
59
+ "pyxle.langserver.command": {
60
+ "type": "string",
61
+ "default": "pyxle-langserver",
62
+ "description": "Command to launch the Pyxle language server. Install via: pip install pyxle-langkit"
63
+ },
64
+ "pyxle.langserver.args": {
65
+ "type": "array",
66
+ "items": { "type": "string" },
67
+ "default": ["--stdio"],
68
+ "description": "Arguments forwarded to the language server command."
69
+ },
70
+ "pyxle.formatting.python": {
71
+ "type": "string",
72
+ "default": "ruff",
73
+ "enum": ["ruff", "black", "none"],
74
+ "description": "Python formatter for .pyx files."
75
+ },
76
+ "pyxle.formatting.jsx": {
77
+ "type": "string",
78
+ "default": "prettier",
79
+ "enum": ["prettier", "none"],
80
+ "description": "JSX formatter for .pyx files."
81
+ },
82
+ "pyxle.diagnostics.pyflakes": {
83
+ "type": "boolean",
84
+ "default": true,
85
+ "description": "Enable pyflakes diagnostics for Python sections."
86
+ },
87
+ "pyxle.diagnostics.react": {
88
+ "type": "boolean",
89
+ "default": true,
90
+ "description": "Enable React/JSX analysis via Babel."
91
+ }
92
+ }
93
+ }
94
+ ]
95
+ },
96
+ "dependencies": {
97
+ "vscode-languageclient": "^9.0.1"
98
+ },
99
+ "devDependencies": {
100
+ "typescript": "^5.3.0",
101
+ "@types/vscode": "^1.85.0",
102
+ "@types/node": "^20.0.0",
103
+ "@vscode/test-electron": "^2.3.0",
104
+ "@vscode/vsce": "^2.22.0"
105
+ }
106
+ }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Pyxle Language Tools — VS Code extension.
3
+ *
4
+ * This is a thin LSP client. All language intelligence (completions, hover,
5
+ * diagnostics, formatting, semantic tokens, go-to-definition) is provided by
6
+ * the ``pyxle-langserver`` Python process. The extension's only job is to
7
+ * launch that process, wire up the Language Client, and manage the status bar.
8
+ *
9
+ * JSX intelligence comes from two sources:
10
+ * 1. The LSP server provides Pyxle-specific completions (components, props)
11
+ * 2. The ``embeddedLanguages`` mapping in the grammar contribution tells
12
+ * VS Code that ``source.js.jsx`` regions are ``javascriptreact``, which
13
+ * enables basic word-based completions and bracket matching from VS Code's
14
+ * built-in TypeScript/JavaScript extension.
15
+ *
16
+ * Full semantic JSX intelligence (type-aware completions, go-to-definition
17
+ * into React types) requires embedding TypeScript's language service in the
18
+ * LSP server — planned for a future release.
19
+ */
20
+
21
+ import * as vscode from "vscode";
22
+ import {
23
+ LanguageClient,
24
+ LanguageClientOptions,
25
+ ServerOptions,
26
+ } from "vscode-languageclient/node";
27
+ import { createStatusBar, updateStatus, StatusState } from "./status";
28
+
29
+ const LANGUAGE_ID = "pyxle";
30
+ const MAX_RETRIES = 3;
31
+ const RETRY_DELAY_MS = 2_000;
32
+
33
+ let client: LanguageClient | undefined;
34
+ let outputChannel: vscode.OutputChannel;
35
+ let statusBar: vscode.StatusBarItem;
36
+
37
+ /* ------------------------------------------------------------------ */
38
+ /* Activation */
39
+ /* ------------------------------------------------------------------ */
40
+
41
+ export function activate(context: vscode.ExtensionContext): void {
42
+ outputChannel = vscode.window.createOutputChannel("Pyxle Language Server");
43
+ context.subscriptions.push(outputChannel);
44
+
45
+ statusBar = createStatusBar(context);
46
+ updateStatus(statusBar, StatusState.Starting);
47
+
48
+ startClient(context, 0);
49
+ }
50
+
51
+ /* ------------------------------------------------------------------ */
52
+ /* Deactivation */
53
+ /* ------------------------------------------------------------------ */
54
+
55
+ export function deactivate(): Thenable<void> | undefined {
56
+ return client?.stop();
57
+ }
58
+
59
+ /* ------------------------------------------------------------------ */
60
+ /* Client lifecycle */
61
+ /* ------------------------------------------------------------------ */
62
+
63
+ function startClient(
64
+ context: vscode.ExtensionContext,
65
+ attempt: number,
66
+ ): void {
67
+ const config = vscode.workspace.getConfiguration("pyxle.langserver");
68
+ const command = config.get<string>("command", "pyxle-langserver");
69
+ const args = config.get<string[]>("args", ["--stdio"]);
70
+
71
+ const serverOptions: ServerOptions = {
72
+ run: { command, args },
73
+ debug: { command, args },
74
+ };
75
+
76
+ const clientOptions: LanguageClientOptions = {
77
+ documentSelector: [{ scheme: "file", language: LANGUAGE_ID }],
78
+ synchronize: {
79
+ fileEvents: vscode.workspace.createFileSystemWatcher("**/*.pyx"),
80
+ },
81
+ outputChannel,
82
+ };
83
+
84
+ client = new LanguageClient(
85
+ "pyxle",
86
+ "Pyxle Language Server",
87
+ serverOptions,
88
+ clientOptions,
89
+ );
90
+
91
+ const startPromise = client.start();
92
+
93
+ client.onDidChangeState((event) => {
94
+ if (event.newState === 2 /* Running */) {
95
+ updateStatus(statusBar, StatusState.Running);
96
+ }
97
+ });
98
+
99
+ const onReady = (): void => {
100
+ updateStatus(statusBar, StatusState.Running);
101
+ };
102
+
103
+ const onError = (error: unknown): void => {
104
+ const message =
105
+ error instanceof Error ? error.message : String(error);
106
+ outputChannel.appendLine(
107
+ `Language server failed to start: ${message}`,
108
+ );
109
+
110
+ if (attempt < MAX_RETRIES) {
111
+ const next = attempt + 1;
112
+ updateStatus(statusBar, StatusState.Retrying, next, MAX_RETRIES);
113
+ outputChannel.appendLine(
114
+ `Retrying in ${RETRY_DELAY_MS}ms (attempt ${next}/${MAX_RETRIES})...`,
115
+ );
116
+ setTimeout(() => startClient(context, next), RETRY_DELAY_MS);
117
+ } else {
118
+ updateStatus(statusBar, StatusState.Failed);
119
+ vscode.window
120
+ .showErrorMessage(
121
+ `Pyxle Language Server failed after ${MAX_RETRIES} attempts. Is pyxle-langserver installed?`,
122
+ "Show Output",
123
+ )
124
+ .then((choice) => {
125
+ if (choice === "Show Output") {
126
+ outputChannel.show();
127
+ }
128
+ });
129
+ }
130
+ };
131
+
132
+ startPromise.then(onReady, onError);
133
+
134
+ context.subscriptions.push({ dispose: () => { client?.stop(); } });
135
+ }