hana-linter 1.0.1 → 1.0.3
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/CHANGELOG.md +15 -0
- package/README.md +23 -23
- package/dist/assets/.hana-linter.json +224 -0
- package/dist/content-lint.js +2 -27
- package/dist/parsers/hdbfunction/__tests__/extractFunctionParameters.test.js +352 -0
- package/dist/parsers/hdbfunction/index.js +42 -0
- package/dist/parsers/hdbfunction/lexer.js +200 -0
- package/dist/parsers/hdbfunction/parser.js +365 -0
- package/dist/parsers/hdbfunction/visitor.js +105 -0
- package/docs/chevrotain-hdbfunction-parser/prd.md +270 -0
- package/docs/chevrotain-hdbfunction-parser/spec.md +980 -0
- package/package.json +3 -2
- package/src/content-lint.ts +2 -35
- package/src/parsers/hdbfunction/__tests__/extractFunctionParameters.test.ts +399 -0
- package/src/parsers/hdbfunction/index.ts +44 -0
- package/src/parsers/hdbfunction/lexer.ts +217 -0
- package/src/parsers/hdbfunction/parser.ts +456 -0
- package/src/parsers/hdbfunction/visitor.ts +118 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
### 1.0.3
|
|
8
|
+
|
|
9
|
+
- Fixed build: `src/assets/.hana-linter.json` is now correctly copied to `dist/assets/` during `pnpm build` via `copyfiles`, ensuring the default config template is bundled in the published package
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### 1.0.2
|
|
14
|
+
|
|
15
|
+
- Added Chevrotain-based `.hdbfunction` parser; content-linting of function input parameters is now fully reliable
|
|
16
|
+
- The `.hdbfunction` parser isolates the parameter list from the `RETURNS` clause and the function body (`AS BEGIN … END`), eliminating false positives caused by `IN` keywords inside SQL body statements and column names in `RETURNS TABLE (...)` definitions
|
|
17
|
+
- HANA functions accept only `IN` parameters; the new parser correctly produces only `inputParameter` subjects and never emits `outputParameter` entries for `.hdbfunction` files
|
|
18
|
+
- Removed the shared ad-hoc regex extractor (`extractProcedureFunctionParameters`) that was previously used for both `.hdbprocedure` and `.hdbfunction` files
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
7
22
|
### 1.0.0
|
|
8
23
|
|
|
9
24
|
- Replaced ad-hoc, line-by-line regex extraction with Chevrotain-based lexer + CST parsers for `.hdbtable`, `.hdbprocedure`, and `.hdbview` files
|
package/README.md
CHANGED
|
@@ -46,23 +46,22 @@ Content-based linting uses [Chevrotain](https://chevrotain.io)-powered lexers an
|
|
|
46
46
|
|
|
47
47
|
> **Work in progress.** Not all artifact types have been migrated to the Chevrotain-based parsing infrastructure yet.
|
|
48
48
|
|
|
49
|
-
| Artifact extension | Content extractor | Status
|
|
50
|
-
| ------------------------- | ---------------------- |
|
|
51
|
-
| `.hdbtable` | Chevrotain lexer + CST | ✅ Migrated
|
|
52
|
-
| `.hdbview` | Chevrotain lexer + CST | ✅ Migrated
|
|
53
|
-
| `.hdbprocedure` | Chevrotain lexer + CST | ✅ Migrated
|
|
54
|
-
| `.hdbfunction` |
|
|
55
|
-
| `.hdbtabletype` | — | ❌ Not implemented |
|
|
56
|
-
| `.hdbcalculationview` | — | ❌ Not implemented |
|
|
57
|
-
| `.hdbanalyticalprivilege` | — | ❌ Not implemented |
|
|
58
|
-
| `.hdbrole` | — | ❌ Not implemented |
|
|
59
|
-
| `.hdbsequence` | — | ❌ Not implemented |
|
|
60
|
-
| `.hdbconstraint` | — | ❌ Not implemented |
|
|
61
|
-
| `.hdbschedulerjob` | — | ❌ Not implemented |
|
|
62
|
-
| `.hdbindex` | — | ❌ Not implemented |
|
|
63
|
-
| `.hdbtrigger` | — | ❌ Not implemented |
|
|
64
|
-
|
|
65
|
-
- **Needs migration**: uses an ad-hoc regex scan, subject to false positives from body keywords, multi-line definitions, and block comments.
|
|
49
|
+
| Artifact extension | Content extractor | Status |
|
|
50
|
+
| ------------------------- | ---------------------- | ---------------------- |
|
|
51
|
+
| `.hdbtable` | Chevrotain lexer + CST | ✅ Migrated |
|
|
52
|
+
| `.hdbview` | Chevrotain lexer + CST | ✅ Migrated |
|
|
53
|
+
| `.hdbprocedure` | Chevrotain lexer + CST | ✅ Migrated |
|
|
54
|
+
| `.hdbfunction` | Chevrotain lexer + CST | ✅ Migrated |
|
|
55
|
+
| `.hdbtabletype` | — | ❌ Not yet implemented |
|
|
56
|
+
| `.hdbcalculationview` | — | ❌ Not yet implemented |
|
|
57
|
+
| `.hdbanalyticalprivilege` | — | ❌ Not yet implemented |
|
|
58
|
+
| `.hdbrole` | — | ❌ Not yet implemented |
|
|
59
|
+
| `.hdbsequence` | — | ❌ Not yet implemented |
|
|
60
|
+
| `.hdbconstraint` | — | ❌ Not yet implemented |
|
|
61
|
+
| `.hdbschedulerjob` | — | ❌ Not yet implemented |
|
|
62
|
+
| `.hdbindex` | — | ❌ Not yet implemented |
|
|
63
|
+
| `.hdbtrigger` | — | ❌ Not yet implemented |
|
|
64
|
+
|
|
66
65
|
- **Not implemented**: `contentRuleSets` targeting these extensions will silently return no results — no identifiers are extracted and no content issues are raised.
|
|
67
66
|
|
|
68
67
|
## Install
|
|
@@ -178,12 +177,13 @@ Each `contentRuleSets` item contains:
|
|
|
178
177
|
|
|
179
178
|
Supported extractors in this version:
|
|
180
179
|
|
|
181
|
-
| `target` | Supported extensions
|
|
182
|
-
| ----------------- |
|
|
183
|
-
| `field` | `.hdbtable`
|
|
184
|
-
| `field` | `.hdbview`
|
|
185
|
-
| `inputParameter` | `.hdbprocedure
|
|
186
|
-
| `
|
|
180
|
+
| `target` | Supported extensions | Extracted identifiers |
|
|
181
|
+
| ----------------- | -------------------- | ---------------------------------------------- |
|
|
182
|
+
| `field` | `.hdbtable` | Column names |
|
|
183
|
+
| `field` | `.hdbview` | Column aliases (explicit list or `AS` aliases) |
|
|
184
|
+
| `inputParameter` | `.hdbprocedure` | `IN` and `INOUT` parameters |
|
|
185
|
+
| `inputParameter` | `.hdbfunction` | `IN` parameters (functions accept `IN` only) |
|
|
186
|
+
| `outputParameter` | `.hdbprocedure` | `OUT` and `INOUT` parameters |
|
|
187
187
|
|
|
188
188
|
### Default Config Example
|
|
189
189
|
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rootDir": "db",
|
|
3
|
+
"ignoredDirectories": ["node_modules", ".git", "gen"],
|
|
4
|
+
"extensionRuleSets": [
|
|
5
|
+
{
|
|
6
|
+
"extension": "hdb*",
|
|
7
|
+
"groups": {
|
|
8
|
+
"all": [
|
|
9
|
+
{
|
|
10
|
+
"description": "Upper snake case only",
|
|
11
|
+
"pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"description": "Max length 30",
|
|
15
|
+
"pattern": "^.{1,30}$",
|
|
16
|
+
"flags": "u"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"extension": ".hdbtable",
|
|
23
|
+
"folderName": "tables",
|
|
24
|
+
"groups": {
|
|
25
|
+
"any": [
|
|
26
|
+
{
|
|
27
|
+
"description": "Prefix T_",
|
|
28
|
+
"pattern": "^T_.+"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"description": "Prefix TX_",
|
|
32
|
+
"pattern": "^TX_.+"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"extension": ".hdbview",
|
|
39
|
+
"folderName": "sqlviews",
|
|
40
|
+
"groups": {
|
|
41
|
+
"all": [
|
|
42
|
+
{
|
|
43
|
+
"description": "Prefix V_",
|
|
44
|
+
"pattern": "^V_.+"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"extension": ".hdbfunction",
|
|
51
|
+
"folderName": "functions",
|
|
52
|
+
"groups": {
|
|
53
|
+
"any": [
|
|
54
|
+
{
|
|
55
|
+
"description": "Prefix TF_",
|
|
56
|
+
"pattern": "^TF_.+"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"description": "Prefix SF_",
|
|
60
|
+
"pattern": "^SF_.+"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"extension": ".hdbprocedure",
|
|
67
|
+
"folderName": "procedures",
|
|
68
|
+
"groups": {
|
|
69
|
+
"all": [
|
|
70
|
+
{
|
|
71
|
+
"description": "Prefix PR_",
|
|
72
|
+
"pattern": "^PR_.+"
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"extension": ".hdbcalculationview",
|
|
79
|
+
"folderName": "models",
|
|
80
|
+
"groups": {
|
|
81
|
+
"all": [
|
|
82
|
+
{
|
|
83
|
+
"description": "Prefix CV_",
|
|
84
|
+
"pattern": "^CV_.+"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"extension": ".hdbanalyticalprivilege",
|
|
91
|
+
"folderName": "authorizations",
|
|
92
|
+
"groups": {
|
|
93
|
+
"all": [
|
|
94
|
+
{
|
|
95
|
+
"description": "Prefix AP_",
|
|
96
|
+
"pattern": "^AP_.+"
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"extension": ".hdbrole",
|
|
103
|
+
"folderName": "roles",
|
|
104
|
+
"groups": {
|
|
105
|
+
"all": [
|
|
106
|
+
{
|
|
107
|
+
"description": "Prefix R_",
|
|
108
|
+
"pattern": "^R_.+"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"extension": ".hdbsequence",
|
|
115
|
+
"folderName": "sequences",
|
|
116
|
+
"groups": {
|
|
117
|
+
"all": [
|
|
118
|
+
{
|
|
119
|
+
"description": "Prefix S_",
|
|
120
|
+
"pattern": "^S_.+"
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"extension": ".hdbtabletype",
|
|
127
|
+
"folderName": "tabletypes",
|
|
128
|
+
"groups": {
|
|
129
|
+
"all": [
|
|
130
|
+
{
|
|
131
|
+
"description": "Prefix TT_",
|
|
132
|
+
"pattern": "^TT_.+"
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"extension": ".hdbconstraint",
|
|
139
|
+
"folderName": "constraints",
|
|
140
|
+
"groups": {
|
|
141
|
+
"all": [
|
|
142
|
+
{
|
|
143
|
+
"description": "Prefix C_",
|
|
144
|
+
"pattern": "^C_.+"
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"extension": ".hdbschedulerjob",
|
|
151
|
+
"folderName": "jobs",
|
|
152
|
+
"groups": {
|
|
153
|
+
"all": [
|
|
154
|
+
{
|
|
155
|
+
"description": "Prefix J_",
|
|
156
|
+
"pattern": "^J_.+"
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"extension": ".hdbindex",
|
|
163
|
+
"folderName": "indexes",
|
|
164
|
+
"groups": {
|
|
165
|
+
"all": [
|
|
166
|
+
{
|
|
167
|
+
"description": "Prefix IDX_",
|
|
168
|
+
"pattern": "^IDX_.+"
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"extension": ".hdbtrigger",
|
|
175
|
+
"folderName": "triggers",
|
|
176
|
+
"groups": {
|
|
177
|
+
"all": [
|
|
178
|
+
{
|
|
179
|
+
"description": "Prefix TR_",
|
|
180
|
+
"pattern": "^TR_.+"
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
"contentRuleSets": [
|
|
187
|
+
{
|
|
188
|
+
"extension": ".hdbtable",
|
|
189
|
+
"target": "field",
|
|
190
|
+
"groups": {
|
|
191
|
+
"all": [
|
|
192
|
+
{
|
|
193
|
+
"description": "Field names in uppercase snake case",
|
|
194
|
+
"pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"extension": ".hdbprocedure",
|
|
201
|
+
"target": "inputParameter",
|
|
202
|
+
"groups": {
|
|
203
|
+
"all": [
|
|
204
|
+
{
|
|
205
|
+
"description": "Input parameters prefixed with IP_",
|
|
206
|
+
"pattern": "^IP_[A-Z0-9_]+$"
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"extension": ".hdbprocedure",
|
|
213
|
+
"target": "outputParameter",
|
|
214
|
+
"groups": {
|
|
215
|
+
"all": [
|
|
216
|
+
{
|
|
217
|
+
"description": "Output parameters prefixed with OP_",
|
|
218
|
+
"pattern": "^OP_[A-Z0-9_]+$"
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
}
|
package/dist/content-lint.js
CHANGED
|
@@ -9,6 +9,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const index_1 = require("./parsers/hdbtable/index");
|
|
10
10
|
const index_2 = require("./parsers/hdbview/index");
|
|
11
11
|
const index_3 = require("./parsers/hdbprocedure/index");
|
|
12
|
+
const index_4 = require("./parsers/hdbfunction/index");
|
|
12
13
|
/**
|
|
13
14
|
* Run content-based naming lint for a file.
|
|
14
15
|
*
|
|
@@ -55,36 +56,10 @@ function extractSubjects(extension, fileContent) {
|
|
|
55
56
|
return (0, index_3.extractProcedureParameters)(fileContent);
|
|
56
57
|
}
|
|
57
58
|
if (extension === '.hdbfunction') {
|
|
58
|
-
return
|
|
59
|
+
return (0, index_4.extractFunctionParameters)(fileContent);
|
|
59
60
|
}
|
|
60
61
|
return [];
|
|
61
62
|
}
|
|
62
|
-
function extractProcedureFunctionParameters(fileContent) {
|
|
63
|
-
const subjects = [];
|
|
64
|
-
const seen = new Set();
|
|
65
|
-
const parameterRegex = /\b(IN|OUT|INOUT)\s+("?[A-Za-z_][A-Za-z0-9_]*"?)\s+[A-Za-z]/gi;
|
|
66
|
-
let match = parameterRegex.exec(fileContent);
|
|
67
|
-
while (match) {
|
|
68
|
-
const mode = match[1];
|
|
69
|
-
const rawName = match[2];
|
|
70
|
-
if (!mode || !rawName) {
|
|
71
|
-
match = parameterRegex.exec(fileContent);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
const normalizedMode = mode.toUpperCase();
|
|
75
|
-
const normalizedName = rawName.replace(/^"|"$/g, '');
|
|
76
|
-
if ((normalizedMode === 'IN' || normalizedMode === 'INOUT') && !seen.has(`input:${normalizedName}`)) {
|
|
77
|
-
seen.add(`input:${normalizedName}`);
|
|
78
|
-
subjects.push({ type: 'inputParameter', name: normalizedName });
|
|
79
|
-
}
|
|
80
|
-
if ((normalizedMode === 'OUT' || normalizedMode === 'INOUT') && !seen.has(`output:${normalizedName}`)) {
|
|
81
|
-
seen.add(`output:${normalizedName}`);
|
|
82
|
-
subjects.push({ type: 'outputParameter', name: normalizedName });
|
|
83
|
-
}
|
|
84
|
-
match = parameterRegex.exec(fileContent);
|
|
85
|
-
}
|
|
86
|
-
return subjects;
|
|
87
|
-
}
|
|
88
63
|
function evaluateAllRules(filePath, extension, subject, rules) {
|
|
89
64
|
const issues = [];
|
|
90
65
|
for (const rule of rules) {
|