tree-sitter-arkts 1.0.0

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.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
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.
22
+
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # tree-sitter-arkts
2
+
3
+ ArkTS 语言的 tree-sitter 解析器,用于语法高亮、代码分析、VSCode 插件等场景。
4
+
5
+ ## 特性
6
+
7
+ - ✅ 完整的 ArkTS 语法支持
8
+ - ✅ 支持 ArkUI 组件语法(component_statement, style_statement)
9
+ - ✅ 支持 struct 声明
10
+ - ✅ 支持装饰器
11
+ - ✅ TypeScript 类型定义
12
+ - ✅ 跨平台支持(Windows, macOS, Linux)
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ npm install tree-sitter-arkts
18
+ ```
19
+
20
+ ## 使用方法
21
+
22
+ ### TypeScript/JavaScript
23
+
24
+ ```typescript
25
+ import { Parser, createParser, parse } from 'tree-sitter-arkts';
26
+
27
+ // 方法 1: 使用便捷函数
28
+ const tree = parse('@Entry()\nstruct MyComponent {\n build() {}\n}');
29
+
30
+ // 方法 2: 创建解析器实例
31
+ const parser = createParser();
32
+ const tree2 = parser.parse(sourceCode);
33
+
34
+ // 方法 3: 手动创建
35
+ import { Parser, ArkTS } from 'tree-sitter-arkts';
36
+ const parser = new Parser();
37
+ parser.setLanguage(ArkTS);
38
+ const tree3 = parser.parse(sourceCode);
39
+ ```
40
+
41
+ ## 开发
42
+
43
+ ### 构建
44
+
45
+ ```bash
46
+ # 生成解析器代码并构建原生模块
47
+ npm run build
48
+
49
+ # 仅生成解析器代码
50
+ npm run generate
51
+
52
+ # 仅编译 TypeScript
53
+ npm run build:ts
54
+ ```
55
+
56
+ ### 测试
57
+
58
+ ```bash
59
+ # 完整功能测试(需要 tree-sitter 原生模块)
60
+ npm test
61
+
62
+ # 仅验证包结构(不需要 tree-sitter 原生模块)
63
+ npm run test:structure
64
+ ```
65
+
66
+ **注意**:
67
+ - 完整功能测试需要 tree-sitter 原生模块
68
+ - **Node.js 版本兼容性**:
69
+ - ✅ **Node.js v24**: 已支持(需要 C++20 编译器,如 GCC 12+)
70
+ - ✅ **Node.js v18/v20/v22**: 完全支持
71
+ - 安装时会自动修复 tree-sitter 的构建配置以支持 Node.js v24
72
+
73
+ ## Windows 构建说明
74
+
75
+ 在 Windows 上构建原生模块需要:
76
+
77
+ 1. **安装构建工具**:
78
+ - 安装 [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022) 或 Visual Studio(包含 C++ 工作负载)
79
+ - 或者安装 [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools): `npm install -g windows-build-tools`
80
+
81
+ 2. **安装 Python**:
82
+ - 确保已安装 Python 2.7 或 3.x
83
+ - node-gyp 需要 Python 来构建原生模块
84
+
85
+ 3. **安装依赖并构建**:
86
+ ```bash
87
+ npm install
88
+ ```
89
+ 这会自动运行 `node-gyp rebuild` 来构建原生模块。
90
+
91
+ ## VSCode 插件使用示例
92
+
93
+ ```typescript
94
+ import { createParser } from 'tree-sitter-arkts';
95
+ import * as vscode from 'vscode';
96
+
97
+ export function activate(context: vscode.ExtensionContext) {
98
+ const parser = createParser();
99
+
100
+ const disposable = vscode.workspace.onDidChangeTextDocument(event => {
101
+ const tree = parser.parse(event.document.getText());
102
+ // 使用语法树进行代码分析、高亮等
103
+ });
104
+
105
+ context.subscriptions.push(disposable);
106
+ }
107
+ ```
108
+
109
+ ## 项目结构
110
+
111
+ - `grammar.js` - ArkTS 语法定义文件
112
+ - `binding.gyp` - Node.js 原生模块构建配置
113
+ - `index.ts` - TypeScript 入口文件
114
+ - `bindings/node/binding.cc` - Node.js 绑定代码
115
+ - `src/` - 由 tree-sitter generate 生成的 C 代码
116
+
117
+ ## 依赖
118
+
119
+ - `tree-sitter` - Tree-sitter 核心库
120
+ - `nan` - Node.js 原生模块开发工具
121
+ - `tree-sitter-typescript` - TypeScript 语法基础(grammar.js 中引用)
122
+
package/binding.gyp ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "tree_sitter_arkts_binding",
5
+ "include_dirs": [
6
+ "<!@(node -p \"require('node-addon-api').include\")",
7
+ "src"
8
+ ],
9
+ "dependencies": [
10
+ "<!(node -p \"require('node-addon-api').gyp\")"
11
+ ],
12
+ "defines": [
13
+ "NAPI_DISABLE_CPP_EXCEPTIONS",
14
+ "NAPI_VERSION=<!(node -p \"process.versions.napi\")"
15
+ ],
16
+ "sources": [
17
+ "src/parser.c",
18
+ "src/scanner.c",
19
+ "bindings/node/binding.cc"
20
+ ],
21
+ "cflags_c": [
22
+ "-std=c99"
23
+ ],
24
+ "cflags_cc": [
25
+ "-std=c++20"
26
+ ],
27
+ "xcode_settings": {
28
+ "OTHER_CPLUSPLUSFLAGS": ["-std=c++20", "-stdlib=libc++"],
29
+ "OTHER_CFLAGS": ["-std=c99"]
30
+ },
31
+ "conditions": [
32
+ ["OS=='mac'", {
33
+ "xcode_settings": {
34
+ "GCC_ENABLE_CPP_EXCEPTIONS": "YES",
35
+ "CLANG_CXX_LIBRARY": "libc++",
36
+ "MACOSX_DEPLOYMENT_TARGET": "10.7"
37
+ }
38
+ }],
39
+ ["OS=='win'", {
40
+ "msvs_settings": {
41
+ "VCCLCompilerTool": {
42
+ "ExceptionHandling": 1
43
+ }
44
+ }
45
+ }]
46
+ ]
47
+ }
48
+ ]
49
+ }
50
+
@@ -0,0 +1,57 @@
1
+ #include "tree_sitter/parser.h"
2
+ #include <napi.h>
3
+
4
+ using namespace Napi;
5
+
6
+ extern "C" TSLanguage * tree_sitter_arkts();
7
+
8
+ namespace {
9
+
10
+ /*
11
+ tstag() {
12
+ b2sum -l64 <(printf tree-sitter) <(printf "$1") | \
13
+ awk '{printf "0x" toupper($1) (NR == 1 ? ", " : "\n")}'
14
+ }
15
+ tstag language # => 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
16
+ */
17
+ const napi_type_tag LANGUAGE_TYPE_TAG = {
18
+ 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
19
+ };
20
+
21
+ Object Init(Env env, Object exports) {
22
+ const TSLanguage *language = tree_sitter_arkts();
23
+
24
+ // 创建 External(不使用 finalizer)
25
+ napi_value external_value;
26
+ napi_status status = napi_create_external(
27
+ env,
28
+ const_cast<TSLanguage *>(language),
29
+ nullptr, // finalizer
30
+ nullptr, // finalizer_hint
31
+ &external_value
32
+ );
33
+
34
+ if (status != napi_ok) {
35
+ Error::New(env, "Failed to create language external").ThrowAsJavaScriptException();
36
+ return exports;
37
+ }
38
+
39
+ // 设置类型标签
40
+ status = napi_type_tag_object(env, external_value, &LANGUAGE_TYPE_TAG);
41
+ if (status != napi_ok) {
42
+ Error::New(env, "Failed to set language type tag").ThrowAsJavaScriptException();
43
+ return exports;
44
+ }
45
+
46
+ // 创建语言对象,包含 language 属性和 name 属性
47
+ Object language_obj = Object::New(env);
48
+ language_obj.Set("language", external_value);
49
+ language_obj.Set("name", String::New(env, "arkts"));
50
+
51
+ return language_obj;
52
+ }
53
+
54
+ NODE_API_MODULE(tree_sitter_arkts_binding, Init)
55
+
56
+ } // namespace
57
+
@@ -0,0 +1,20 @@
1
+ import Parser = require('tree-sitter');
2
+ import { Tree } from 'tree-sitter';
3
+ /**
4
+ * ArkTS 语言对象
5
+ */
6
+ export declare const ArkTS: any;
7
+ /**
8
+ * 创建并配置一个解析器实例
9
+ * @returns 配置好的 Parser 实例
10
+ */
11
+ export declare function createParser(): Parser;
12
+ /**
13
+ * 解析 ArkTS 源代码
14
+ * @param sourceCode 要解析的源代码
15
+ * @param oldTree 可选的旧语法树,用于增量解析
16
+ * @returns 解析后的语法树
17
+ */
18
+ export declare function parse(sourceCode: string, oldTree?: Tree): Tree;
19
+ export { Tree };
20
+ export { Parser };
package/dist/index.js ADDED
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.Parser = exports.ArkTS = void 0;
37
+ exports.createParser = createParser;
38
+ exports.parse = parse;
39
+ const Parser = require("tree-sitter");
40
+ exports.Parser = Parser;
41
+ const path = __importStar(require("path"));
42
+ // 动态加载原生绑定模块(优先使用预编译版本)
43
+ let ParserBinding;
44
+ try {
45
+ // 尝试使用 node-gyp-build 加载预编译版本
46
+ ParserBinding = require('node-gyp-build')(path.join(__dirname, '..'));
47
+ }
48
+ catch (err) {
49
+ // 回退到本地构建版本
50
+ const rootDir = path.resolve(__dirname, '..');
51
+ try {
52
+ ParserBinding = require(path.join(rootDir, 'build/Release/tree_sitter_arkts_binding.node'));
53
+ }
54
+ catch (err2) {
55
+ try {
56
+ ParserBinding = require(path.join(rootDir, 'build/Debug/tree_sitter_arkts_binding.node'));
57
+ }
58
+ catch (err3) {
59
+ throw new Error('tree-sitter-arkts 原生模块未找到。请运行 npm install 或 npm run build 来构建模块。');
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * ArkTS 语言对象
65
+ */
66
+ exports.ArkTS = ParserBinding;
67
+ /**
68
+ * 创建并配置一个解析器实例
69
+ * @returns 配置好的 Parser 实例
70
+ */
71
+ function createParser() {
72
+ const parser = new Parser();
73
+ parser.setLanguage(exports.ArkTS);
74
+ return parser;
75
+ }
76
+ /**
77
+ * 解析 ArkTS 源代码
78
+ * @param sourceCode 要解析的源代码
79
+ * @param oldTree 可选的旧语法树,用于增量解析
80
+ * @returns 解析后的语法树
81
+ */
82
+ function parse(sourceCode, oldTree) {
83
+ const parser = createParser();
84
+ return parser.parse(sourceCode, oldTree);
85
+ }
package/grammar.js ADDED
@@ -0,0 +1,123 @@
1
+ /* eslint-disable valid-jsdoc */
2
+ const tsGrammar = require('tree-sitter-typescript/typescript/grammar.js');
3
+
4
+ // extend
5
+ module.exports = grammar(tsGrammar, {
6
+ name: 'arkts',
7
+
8
+ precedences: ($, previous) => previous.concat([
9
+ [$.call_expression, $.component_statement],
10
+ [$.style_expression, $.statement],
11
+ [$.style_expression, $.statement_block],
12
+ ]),
13
+
14
+ rules: {
15
+ // method_signature add decorator
16
+ method_signature: ($) => seq(
17
+ repeat(field('decorator', $.decorator)),
18
+ optional($.accessibility_modifier),
19
+ optional('static'),
20
+ optional($.override_modifier),
21
+ optional('readonly'),
22
+ optional('async'),
23
+ optional(choice('get', 'set', '*')),
24
+ field('name', $._property_name),
25
+ optional('?'),
26
+ $._call_signature,
27
+ ),
28
+
29
+ // struct declaration
30
+ struct_declaration: ($) => prec('literal', seq(
31
+ repeat(field('decorator', $.decorator)),
32
+ 'struct',
33
+ field('name', optional($._type_identifier)),
34
+ field('body', $.class_body),
35
+ )),
36
+
37
+ declaration: ($, previous) => choice(
38
+ previous,
39
+ $.struct_declaration,
40
+ ),
41
+
42
+ // ambient add decorator
43
+ ambient_declaration: ($) => seq(
44
+ repeat(field('decorator', $.decorator)),
45
+ 'declare',
46
+ choice(
47
+ $.declaration,
48
+ seq('global', $.statement_block),
49
+ seq('module', '.', alias($.identifier, $.property_identifier), ':', $._type, $._semicolon),
50
+ ),
51
+ ),
52
+
53
+ // function add decorator
54
+ function_declaration: ($) => prec.right('declaration', seq(
55
+ repeat(field('decorator', $.decorator)),
56
+ optional('async'),
57
+ 'function',
58
+ field('name', $.identifier),
59
+ $._call_signature,
60
+ field('body', $.statement_block),
61
+ optional($._automatic_semicolon),
62
+ )),
63
+
64
+ /**
65
+ * ArkUI component statement
66
+ *
67
+ * @example:
68
+ * XXXX('test') {
69
+ * Row()
70
+ * }
71
+ * .width(10)
72
+ */
73
+ component_statement: ($) => prec.right(seq(
74
+ field('function', $.expression),
75
+ field('arguments', $.arguments),
76
+ optional($.statement_block),
77
+ optional($.style_statement),
78
+ )),
79
+
80
+ /**
81
+ * ArkUI style statement
82
+ *
83
+ * @example:
84
+ * .width(10)
85
+ * .height(10)
86
+ */
87
+ style_statement: ($) => prec.right(repeat1(seq(
88
+ '.',
89
+ field('function', $.identifier),
90
+ field('arguments', $.arguments),
91
+ ))),
92
+
93
+ /**
94
+ * match stateStyles
95
+ *
96
+ * @example:
97
+ * Button()
98
+ * .normal: {
99
+ * .backgroundColor(Color.Yellow)
100
+ * }
101
+ * focused: {
102
+ * .backgroundColor(Color.Pink)
103
+ * }
104
+ */
105
+ style_expression: ($) => prec.left(1, seq(
106
+ '{',
107
+ $.style_statement,
108
+ '}',
109
+ )),
110
+
111
+ primary_expression: ($, previous) => choice(
112
+ previous,
113
+ $.style_expression,
114
+ ),
115
+
116
+ statement: ($, previous) => choice(
117
+ previous,
118
+ $.component_statement,
119
+ $.style_statement,
120
+ ),
121
+ },
122
+ });
123
+
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "tree-sitter-arkts",
3
+ "version": "1.0.0",
4
+ "description": "ArkTS grammar for tree-sitter",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "keywords": [
8
+ "tree-sitter",
9
+ "arkts",
10
+ "parser",
11
+ "harmonyos",
12
+ "arkui"
13
+ ],
14
+ "author": "",
15
+ "license": "MIT",
16
+ "files": [
17
+ "dist",
18
+ "prebuilds",
19
+ "src",
20
+ "bindings/node/binding.cc",
21
+ "binding.gyp",
22
+ "grammar.js",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
26
+ "dependencies": {
27
+ "node-addon-api": "^8.5.0",
28
+ "node-gyp-build": "^4.8.0",
29
+ "tree-sitter": "^0.25.0",
30
+ "tree-sitter-javascript": "^0.20.4",
31
+ "tree-sitter-typescript": "^0.20.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.0.0",
35
+ "node-gyp-build": "^4.8.0",
36
+ "prebuildify": "^6.0.1",
37
+ "tree-sitter-cli": "^0.20.0",
38
+ "typescript": "^5.0.0"
39
+ },
40
+ "scripts": {
41
+ "generate": "npx tree-sitter generate",
42
+ "build": "npx tree-sitter generate && node-gyp rebuild && npm run build:ts",
43
+ "build:ts": "tsc",
44
+ "prebuild": "npm run generate && prebuildify --napi",
45
+ "prebuild:win32": "npm run generate && prebuildify --napi --platform win32",
46
+ "prebuild:linux": "npm run generate && prebuildify --napi --platform linux",
47
+ "prebuild:darwin": "npm run generate && prebuildify --napi --platform darwin",
48
+ "install": "node-gyp-build || npm run install:fallback",
49
+ "install:fallback": "npm run fix-tree-sitter && node-gyp rebuild",
50
+ "fix-tree-sitter": "node fix-tree-sitter.js",
51
+ "postinstall": "npm run fix-tree-sitter && (npm rebuild tree-sitter || true)",
52
+ "test": "node test.js",
53
+ "test:structure": "node test-structure.js",
54
+ "prepublishOnly": "npm run generate && npm run build:ts"
55
+ },
56
+ "repository": {
57
+ "type": "git",
58
+ "url": ""
59
+ },
60
+ "engines": {
61
+ "node": ">=14.0.0"
62
+ },
63
+ "gypfile": true,
64
+ "os": [
65
+ "darwin",
66
+ "linux",
67
+ "win32"
68
+ ],
69
+ "cpu": [
70
+ "x64",
71
+ "arm64"
72
+ ]
73
+ }