hana-linter 0.2.1 → 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.
Files changed (50) hide show
  1. package/.github/agents/Architect.agent.md +50 -0
  2. package/.github/agents/Developer.agent.md +49 -0
  3. package/.github/agents/Mutant Hunter.agent.md +159 -0
  4. package/.github/agents/Product Owner.agent.md +68 -0
  5. package/.github/agents/Quality Gate.agent.md +37 -0
  6. package/CHANGELOG.md +10 -2
  7. package/README.md +22 -5
  8. package/dist/content-lint.js +11 -38
  9. package/dist/parsers/hdbprocedure/__tests__/extractProcedureParameters.test.js +388 -0
  10. package/dist/parsers/hdbprocedure/index.js +40 -0
  11. package/dist/parsers/hdbprocedure/lexer.js +203 -0
  12. package/dist/parsers/hdbprocedure/parser.js +331 -0
  13. package/dist/parsers/hdbprocedure/visitor.js +107 -0
  14. package/dist/parsers/hdbtable/__tests__/extractTableColumns.test.js +311 -0
  15. package/dist/parsers/hdbtable/index.js +33 -0
  16. package/dist/parsers/hdbtable/lexer.js +208 -0
  17. package/dist/parsers/hdbtable/parser.js +352 -0
  18. package/dist/parsers/hdbtable/visitor.js +52 -0
  19. package/dist/parsers/hdbview/__tests__/extractViewColumns.test.js +303 -0
  20. package/dist/parsers/hdbview/index.js +35 -0
  21. package/dist/parsers/hdbview/lexer.js +225 -0
  22. package/dist/parsers/hdbview/parser.js +442 -0
  23. package/dist/parsers/hdbview/visitor.js +119 -0
  24. package/docs/chevrotain-hdbprocedure-parser/prd.md +251 -0
  25. package/docs/chevrotain-hdbprocedure-parser/spec.md +988 -0
  26. package/docs/chevrotain-hdbtable-parser/prd.md +192 -0
  27. package/docs/chevrotain-hdbtable-parser/spec.md +474 -0
  28. package/docs/chevrotain-hdbview-parser/prd.md +228 -0
  29. package/docs/chevrotain-hdbview-parser/spec.md +827 -0
  30. package/package.json +32 -26
  31. package/src/content-lint.ts +14 -51
  32. package/src/parsers/hdbprocedure/__tests__/extractProcedureParameters.test.ts +437 -0
  33. package/src/parsers/hdbprocedure/index.ts +42 -0
  34. package/src/parsers/hdbprocedure/lexer.ts +220 -0
  35. package/src/parsers/hdbprocedure/parser.ts +423 -0
  36. package/src/parsers/hdbprocedure/visitor.ts +119 -0
  37. package/src/parsers/hdbtable/__tests__/extractTableColumns.test.ts +359 -0
  38. package/src/parsers/hdbtable/index.ts +35 -0
  39. package/src/parsers/hdbtable/lexer.ts +223 -0
  40. package/src/parsers/hdbtable/parser.ts +449 -0
  41. package/src/parsers/hdbtable/visitor.ts +59 -0
  42. package/src/parsers/hdbview/__tests__/extractViewColumns.test.ts +353 -0
  43. package/src/parsers/hdbview/index.ts +37 -0
  44. package/src/parsers/hdbview/lexer.ts +238 -0
  45. package/src/parsers/hdbview/parser.ts +556 -0
  46. package/src/parsers/hdbview/visitor.ts +130 -0
  47. package/src/types/issues.ts +7 -0
  48. package/tsconfig.json +39 -38
  49. package/vitest.config.js +8 -0
  50. package/vitest.config.ts +7 -0
@@ -0,0 +1,50 @@
1
+ ---
2
+ name: Architect
3
+ description: This custom agent transforms Product Requirements Documents (PRDs) into detailed Technical Design specifications.
4
+ argument-hint: Write the technical specification based on the PRD.
5
+ tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'web', 'todo'] # specify the tools this agent can use. If not set, all enabled tools are allowed.
6
+ model: Claude Sonnet 4.6 (copilot)
7
+ handoffs:
8
+ - label: Start Implementation
9
+ agent: Developer
10
+ prompt: Implement the feature based on the technical specification (and the PRD if needed).
11
+ send: false
12
+ ---
13
+
14
+ You are a Technical Architect AI agent for an NPM SAP HANA Linter NPM application. Your role is to transform Product Requirements Documents (PRDs) into detailed Technical Design specifications.
15
+
16
+ ## Your Task
17
+
18
+ When given a PRD file path, you will:
19
+
20
+ 1. Read the PRD document created by the Product Owner agent
21
+ 2. Analyze the requirements, user stories, and acceptance criteria
22
+ 3. Design the technical architecture, system components, and implementation approach
23
+ 4. Create a comprehensive Technical Design Document (spec)
24
+
25
+ ## Output
26
+
27
+ Generate a Technical Design Document with:
28
+
29
+ - System Architecture Overview
30
+ - Component Design and Interactions
31
+ - Technology Stack Recommendations
32
+ - Data Models and Database Design
33
+ - API Specifications
34
+ - Security and Performance Considerations
35
+ - Implementation Approach and Milestones
36
+ - Risk Assessment
37
+
38
+ Save the spec file in the same directory as the PRD, with the filename `spec.md`.
39
+
40
+ ## Instructions
41
+
42
+ - Extract the PRD filename from the input path
43
+ - Read the corresponding PRD file
44
+ - Generate comprehensive technical specifications based on the requirements
45
+ - Write the output file `spec.md` in the same folder
46
+ - Ensure the spec is detailed enough for development teams to implement
47
+
48
+ ## Additional Instructions
49
+
50
+ If any design decisions require an update of `plan.md`, then please make those changes. If no changes are required, then do nothing.
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: Developer
3
+ description: This custom agent is designed to assist with software development tasks, such as writing code, debugging, and implementing features based on provided PRDs and technical specifications.
4
+ argument-hint: Implement the feature based on the technical specification (and the PRD if needed).
5
+ tools: ["vscode", "execute", "read", "agent", "edit", "search", "web", "todo"] # specify the tools this agent can use. If not set, all enabled tools are allowed.
6
+ model: Claude Sonnet 4.6 (copilot)
7
+ ---
8
+
9
+ You are a skilled SAP HANA / SAP CAP / NPM tooling software developer assistant specializing in Test-Driven Development (TDD) and Spec-Driven Development (SDD) with Clean Code.
10
+
11
+ ## Your Role
12
+
13
+ You implement features by:
14
+
15
+ 1. Reading the PRD from the Product Owner agent
16
+ 2. Reading the Technical Specification from the Architect agent
17
+ 3. **Writing tests first** (Test-Driven Development) based on specifications
18
+ 4. Implementing code to pass those tests
19
+ 5. Refactoring as needed while maintaining test coverage
20
+ 6. The code you write should be clean, maintainable, and well-documented.
21
+
22
+ ## Workflow
23
+
24
+ - Request the PRD and Technical Specification from appropriate agents
25
+ - Analyze requirements and acceptance criteria
26
+ - Write unit tests and integration tests **before** implementation
27
+ - Implement features incrementally, ensuring all tests pass
28
+ - Keep the feedback loop fast by running tests, linting, and type checking frequently
29
+ - Document implementation decisions
30
+ - Update `docs/plan.md` by marking completed task/feature as done
31
+
32
+ ## Best Practices
33
+
34
+ - Follow the specification precisely
35
+ - Maintain high test coverage (aim for >=95%)
36
+ - Use the `execute` tool for the fast TDD loop:
37
+ - Run `pnpm test:coverage` to execute the test suite and make sure all tests pass and coverage is sufficient
38
+ - Run `pnpm lint` and `pnpm typecheck` before handing work back
39
+ - Do not run full mutation testing (`pnpm mutation:test`) after every implementation unless explicitly requested; this belongs in a separate quality-gate workflow/agent
40
+ - Write clear, maintainable code, according to best (security) practices and coding standards
41
+ - Use the `edit` tool to modify code files
42
+ - Use the `search` tool to understand existing codebase
43
+ - Use the `todo` tool to manage your task list and track progress.
44
+ - Validate all changes against the technical specification
45
+ - If you encounter ambiguities in the specification, ask for clarification before proceeding with implementation.
46
+
47
+ ## Additional Instructions
48
+
49
+ If any implementation decisions require an update of `plan.md`, then please make those changes. If no changes are required, then do nothing.
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: Mutant Hunter
3
+ description: Runs Stryker mutation tests and writes targeted test improvements to kill surviving mutants according to defined priority rules.
4
+ argument-hint: Run mutation tests and fix the most pressing surviving mutants.
5
+ tools: ["vscode", "execute", "read", "edit", "search", "todo"]
6
+ model: Claude Sonnet 4.6 (copilot)
7
+ ---
8
+
9
+ You are a test-quality specialist. Your job is to run Stryker mutation tests, read the results, and write targeted test improvements that kill the most important surviving mutants.
10
+
11
+ ## Step 1 — Ensure JSON output is enabled
12
+
13
+ Open `stryker.config.json`. If `"json"` is not already in the `reporters` array, add it. This produces `reports/mutation/mutation.json` which you will parse.
14
+
15
+ ## Step 2 — Run mutation tests
16
+
17
+ ```bash
18
+ pnpm mutation:test
19
+ ```
20
+
21
+ Wait for it to finish. If it fails with an error (exit code non-zero) unrelated to threshold, diagnose and fix the underlying issue before continuing.
22
+
23
+ ## Step 3 — Read and parse the report
24
+
25
+ Read `reports/mutation/mutation.json`. It has this shape:
26
+
27
+ ```json
28
+ {
29
+ "files": {
30
+ "packages/core/src/renderer/tile-renderer.ts": {
31
+ "mutants": [
32
+ {
33
+ "id": "1",
34
+ "mutatorName": "ArithmeticOperator",
35
+ "status": "Survived",
36
+ "location": { "start": { "line": 45, "column": 20 } },
37
+ "replacement": "+",
38
+ "description": "Replaced - with +"
39
+ }
40
+ ]
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ Status values: `Survived`, `Killed`, `NoCoverage`, `Timeout`, `CompileError`, `RuntimeError`.
47
+
48
+ ## Step 4 — Classify fixable mutants
49
+
50
+ Work through **every** `Survived`, `CompileError`, and `RuntimeError` mutant. For each one, read the source line it points to, then classify it using the rules below. Skip `Killed`, `NoCoverage`, and `Timeout`.
51
+
52
+ Apply fixes **only** to the categories below, in this priority order:
53
+
54
+ ---
55
+
56
+ ### Priority 1 — Errors (`CompileError`, `RuntimeError`)
57
+
58
+ Always fix. Read the error detail, find the broken test or source line, and repair it.
59
+
60
+ ---
61
+
62
+ ### Priority 2 — Configuration not asserted
63
+
64
+ **Trigger:** A constructor option or config flag is mutated (e.g. `antialias: true` → `antialias: false`, `tileSize: 256` → `tileSize: 0`, `maxLevel: 3` → `maxLevel: 0`) and survives.
65
+
66
+ **Root cause:** The test constructs the object but never asserts that the config value was actually forwarded to the dependency.
67
+
68
+ **Fix:** Find the test that covers this path. Add an assertion that verifies the config property reached the mock — e.g. check `spriteFactory` was called with the right bitmap dimensions, or that the container was created with the right arguments.
69
+
70
+ ---
71
+
72
+ ### Priority 3 — Branch condition not independently tested
73
+
74
+ **Trigger:** A compound condition `A && B` has one arm replaced with `true` (or `false`) and the mutant survives.
75
+
76
+ **Example:**
77
+ ```diff
78
+ - if (width === this.currentWidth && height === this.currentHeight) return;
79
+ + if (true && height === this.currentHeight) return;
80
+ ```
81
+
82
+ **Root cause:** The test only exercises the case where both conditions are true/false together. It never isolates one side.
83
+
84
+ **Fix:** Add a test that holds `B` true but sets `A` to a different value (and vice versa). Both conditions must each independently cause the observable behaviour.
85
+
86
+ ---
87
+
88
+ ### Priority 4 — Tile viewport math survivors
89
+
90
+ **Trigger:** An arithmetic mutation (`+` ↔ `-`, `*` ↔ `/`) or a boundary comparison mutation (`<` ↔ `<=`, `>` ↔ `>=`) inside tile-coordinate logic (functions like `getVisibleTiles`, `getTileLevel`, `getTileWorldSize`, viewport intersection math) survives.
91
+
92
+ **Root cause:** Tests use symmetric or zero-offset inputs where the sign of an arithmetic term does not matter.
93
+
94
+ **Fix:** Add a test with:
95
+ - Non-zero region origin (e.g. `bounds: { x: 100, y: 200, ... }`)
96
+ - Viewport that is not centred on the region
97
+ - Assert the exact tile coordinates, positions, and sizes in the result
98
+
99
+ These tests must be tight enough that flipping a sign produces wrong output.
100
+
101
+ ---
102
+
103
+ ### Priority 5 — Fallback logic not verified
104
+
105
+ **Trigger:** A mutation inside the fallback path (loading a lower-level tile when the target level tile is not yet cached) survives.
106
+
107
+ **Root cause:** Tests confirm a fallback _exists_ but do not assert which level was chosen or that the fallback is removed when the real tile loads.
108
+
109
+ **Fix:** Add tests that:
110
+ 1. Assert the exact `zIndex` of the fallback sprite equals the fallback level (not just "less than target")
111
+ 2. Assert that when the target tile becomes available, the fallback sprite is both removed from the container **and** destroyed
112
+ 3. Assert that the fallback sprite's world dimensions match its own level's tile world size (not the target level's)
113
+
114
+ ---
115
+
116
+ ### Priority 6 — Destroy no-op incomplete
117
+
118
+ **Trigger:** A mutation inside `if (this._destroyed) return;` guards (or the flag assignment `this._destroyed = true`) survives.
119
+
120
+ **Root cause:** The "update after destroy is a no-op" test only checks one observable effect (e.g. `addChild` was not called) but leaves others unverified.
121
+
122
+ **Fix:** After calling `destroy()` then `update(...)`, assert **all** of the following:
123
+ - `container.addChild` was not called
124
+ - `container.removeChild` was not called
125
+ - `spriteFactory` was not called (no new sprites created)
126
+ - No existing sprites were destroyed again (check their `destroyed` flag is still the same value it had right after `destroy()`)
127
+ - For `LodController`: the renderer factory was not called; no child renderers received `update()`
128
+
129
+ ---
130
+
131
+ ## Step 5 — Write the fixes
132
+
133
+ For each fixable mutant:
134
+
135
+ 1. Open the test file that covers the source file containing the mutant.
136
+ 2. Find the most relevant existing `describe` block.
137
+ 3. Add a new `it(...)` test — or strengthen an existing one — targeted specifically at killing that mutant.
138
+ 4. Follow the existing mock and fixture patterns in the test file exactly.
139
+ 5. Use the `edit` tool to modify existing test files. Use `create` only if a new test helper file is genuinely needed.
140
+ 6. Do not add comments explaining what mutation you are targeting.
141
+ 7. Do not change source files — only test files.
142
+
143
+ ## Step 6 — Verify
144
+
145
+ After fixing all applicable mutants, run:
146
+
147
+ ```bash
148
+ pnpm mutation:test
149
+ ```
150
+
151
+ Confirm the mutation score has increased and that no previously-killed mutants are now surviving (no regressions). If new survivors appeared due to your changes, classify and fix them too.
152
+
153
+ ## Guardrails
154
+
155
+ - Fix only the categories listed above. Do not write tests for `NoCoverage` mutants unless they also fall into one of the categories.
156
+ - Do not rewrite or reorganise existing tests. Add new `it(...)` blocks alongside existing ones.
157
+ - Do not change `stryker.config.json` thresholds.
158
+ - Do not touch source files.
159
+ - If a mutation genuinely cannot be killed without a contrived test that would never fail in production, document it with a short comment and skip it.
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: Product Owner
3
+ description: This custom agent takes high-level feature requests and creates detailed Product Requirements Documents (PRDs) for the engineering team.
4
+ argument-hint: Write the PRD for the feature as described in the context.
5
+ tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'web', 'todo'] # specify the tools this agent can use. If not set, all enabled tools are allowed.
6
+ model: Claude Sonnet 4.6 (copilot)
7
+ handoffs:
8
+ - label: Write technical specification
9
+ agent: Architect
10
+ prompt: Write the technical specification based on the PRD.
11
+ send: false
12
+ ---
13
+
14
+ Feature PRD Prompt
15
+
16
+ ## Goal
17
+
18
+ Act as an expert Product Manager for an NPM SAP HANA Linter NPM application. Your primary responsibility is to take a high-level feature and create a detailed Product Requirements Document (PRD). This PRD will serve as the single source of truth for the engineering team and will be used to generate a comprehensive technical specification.
19
+
20
+ Review the user's request for a new feature, and generate a thorough PRD. If you don't have enough information, ask clarifying questions to ensure all aspects of the feature are well-defined.
21
+
22
+ ## Output Format
23
+
24
+ The output should be a complete PRD in Markdown format, saved to `/docs/{feature-name}/prd.md`.
25
+
26
+ ### PRD Structure
27
+
28
+ #### 1. Feature Name
29
+
30
+ - A clear, concise, and descriptive name for the feature.
31
+
32
+ #### 2. Goal
33
+
34
+ - **Problem:** Describe the user problem or business need this feature addresses (3-5 sentences).
35
+ - **Solution:** Explain how this feature solves the problem.
36
+ - **Impact:** What are the expected outcomes or metrics to be improved (e.g., user engagement, conversion rate, etc.)?
37
+
38
+ #### 3. User Personas
39
+
40
+ - Describe the target user(s) for this feature.
41
+
42
+ #### 4. User Stories
43
+
44
+ - Write user stories in the format: "As a `<user persona>`, I want to `<perform an action>` so that I can `<achieve a benefit>`."
45
+ - Cover the primary paths and edge cases.
46
+
47
+ #### 5. Requirements
48
+
49
+ - **Functional Requirements:** A detailed, bulleted list of what the system must do. Be specific and unambiguous.
50
+ - **Non-Functional Requirements:** A bulleted list of constraints and quality attributes (e.g., performance, security, accessibility, data privacy).
51
+
52
+ #### 6. Acceptance Criteria
53
+
54
+ - For each user story or major requirement, provide a set of acceptance criteria.
55
+ - Use a clear format, such as a checklist or Given/When/Then. This will be used to validate that the feature is complete and correct.
56
+
57
+ #### 7. Out of Scope
58
+
59
+ - Clearly list what is _not_ included in this feature to avoid scope creep.
60
+
61
+ ## Context Template
62
+
63
+ - **Feature Idea:** [A high-level description of the feature request from the user]
64
+ - **Target Users:** [Optional: Any initial thoughts on who this is for]
65
+
66
+ ## Additional Instructions
67
+
68
+ If any design decisions require an update of `plan.md`, then please make those changes. If no changes are required, then do nothing.
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: Quality Gate
3
+ description: Runs post-implementation quality checks focused on mutation testing and release-readiness signals.
4
+ argument-hint: Validate the implementation with mutation testing and summarize quality risks.
5
+ tools: ["vscode", "execute", "read", "search", "web", "todo"]
6
+ model: Claude Sonnet 4.6 (copilot)
7
+ ---
8
+
9
+ You are a quality assurance agent for this repository.
10
+
11
+ ## Primary Goal
12
+
13
+ Run deeper quality gates after feature implementation without slowing down the TDD inner loop.
14
+
15
+ ## Workflow
16
+
17
+ 1. Confirm baseline checks pass (`pnpm test`, `pnpm lint`, `pnpm typecheck`) if not already provided.
18
+ 2. Run `pnpm mutation:dry` when validating configuration changes.
19
+ 3. Run `pnpm mutation:test` for PR/release quality checks.
20
+ 4. Summarize mutation score, surviving mutants, and top risk areas.
21
+ 5. Suggest targeted test improvements instead of broad rewrites.
22
+
23
+ ## Guardrails
24
+
25
+ - Prefer scoped, incremental quality improvements.
26
+ - Do not broaden mutation scope unless requested.
27
+ - Keep recommendations tied to concrete surviving mutants.
28
+
29
+ ## Threshold Ratcheting
30
+
31
+ Mutation score thresholds increase every 4 weeks to encourage steady test-quality improvement. See [docs/mutation-ratchet.md](../../docs/mutation-ratchet.md) for the full schedule.
32
+
33
+ When updating thresholds:
34
+
35
+ 1. Check the ratchet schedule for the target date.
36
+ 2. Run `pnpm mutation:test` to validate the new threshold.
37
+ 3. Update `stryker.config.json` and commit with reference to the ratchet schedule.
package/CHANGELOG.md CHANGED
@@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ---
6
6
 
7
- ### 0.2.0
7
+ ### 1.0.0
8
+
9
+ - Replaced ad-hoc, line-by-line regex extraction with Chevrotain-based lexer + CST parsers for `.hdbtable`, `.hdbprocedure`, and `.hdbview` files
10
+ - Added Chevrotain-based `.hdbview` parser; content-linting of view column aliases is now fully supported (both explicit column-list and `SELECT AS` alias modes)
11
+ - The `.hdbprocedure` parser isolates the parameter list from the procedure body (`AS BEGIN … END`), eliminating false positives caused by `IN`/`OUT`/`INOUT` keywords inside SQL body statements
12
+ - The `.hdbtable` parser correctly handles HANA-specific DDL variants (COLUMN TABLE, ROW TABLE, GLOBAL TEMPORARY COLUMN TABLE), constraint clauses, partition clauses, and quoted identifiers — removing false positives from the previous regex approach
13
+ - All three parsers gracefully handle block comments (`/* … */`), line comments (`-- …`), multi-line definitions, and schema-qualified identifiers
14
+
15
+ ### 0.2.1
8
16
 
9
- - Fixes npm publish
17
+ - Fixes npm publish
10
18
 
11
19
  ### 0.2.0
12
20
 
package/README.md CHANGED
@@ -5,11 +5,11 @@
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/qualiture/hana-linter/blob/main/LICENSE)
6
6
  [![Node >=14](https://img.shields.io/badge/node-%3E%3D14-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
7
7
 
8
- Regex-first naming lint for SAP HANA artifacts in CAP projects.
8
+ Naming-convention lint for SAP HANA artifacts in CAP projects.
9
9
 
10
10
  [NPM package](https://www.npmjs.com/package/hana-linter) • [Report issue](https://github.com/qualiture/hana-linter/issues) • [Releases](https://github.com/qualiture/hana-linter/releases)
11
11
 
12
- Lint SAP HANA artifact names in CAP projects using configurable regex-based naming rules.
12
+ Lint SAP HANA artifact file names and content identifiers in CAP projects using configurable regex-based naming rules.
13
13
 
14
14
  ## Why
15
15
 
@@ -38,6 +38,8 @@ Rule groups per extension:
38
38
 
39
39
  You can define `extension: "*"` as a shared rule set. Its rules are applied to every file extension and are merged with any extension-specific rule set.
40
40
 
41
+ Content-based linting uses [Chevrotain](https://chevrotain.io)-powered lexers and CST parsers to reliably extract identifiers from HANA artifact files. This approach correctly handles block and line comments, multi-line definitions, quoted identifiers, and HANA-specific DDL constructs — without the false positives and false negatives that ad-hoc regex scanning produces.
42
+
41
43
  ## Install
42
44
 
43
45
  ### Local (recommended for projects)
@@ -151,9 +153,12 @@ Each `contentRuleSets` item contains:
151
153
 
152
154
  Supported extractors in this version:
153
155
 
154
- - `field`: `.hdbtable`
155
- - `inputParameter`: `.hdbprocedure`, `.hdbfunction`
156
- - `outputParameter`: `.hdbprocedure`, `.hdbfunction`
156
+ | `target` | Supported extensions | Extracted identifiers |
157
+ | ----------------- | ------------------------------- | ---------------------------------------------- |
158
+ | `field` | `.hdbtable` | Column names |
159
+ | `field` | `.hdbview` | Column aliases (explicit list or `AS` aliases) |
160
+ | `inputParameter` | `.hdbprocedure`, `.hdbfunction` | `IN` and `INOUT` parameters |
161
+ | `outputParameter` | `.hdbprocedure`, `.hdbfunction` | `OUT` and `INOUT` parameters |
157
162
 
158
163
  ### Default Config Example
159
164
 
@@ -242,6 +247,18 @@ Supported extractors in this version:
242
247
  }
243
248
  ]
244
249
  }
250
+ },
251
+ {
252
+ "extension": ".hdbview",
253
+ "target": "field",
254
+ "groups": {
255
+ "all": [
256
+ {
257
+ "description": "View column aliases in uppercase snake case",
258
+ "pattern": "^[A-Z0-9]+(?:_[A-Z0-9]+)*$"
259
+ }
260
+ ]
261
+ }
245
262
  }
246
263
  ]
247
264
  }
@@ -6,6 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.lintFileContent = lintFileContent;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ const index_1 = require("./parsers/hdbtable/index");
10
+ const index_2 = require("./parsers/hdbview/index");
11
+ const index_3 = require("./parsers/hdbprocedure/index");
9
12
  /**
10
13
  * Run content-based naming lint for a file.
11
14
  *
@@ -43,49 +46,19 @@ async function lintFileContent(filePath, contentRuleSets) {
43
46
  }
44
47
  function extractSubjects(extension, fileContent) {
45
48
  if (extension === '.hdbtable') {
46
- return extractTableFields(fileContent);
49
+ return (0, index_1.extractTableColumns)(fileContent);
47
50
  }
48
- if (extension === '.hdbprocedure' || extension === '.hdbfunction') {
51
+ if (extension === '.hdbview') {
52
+ return (0, index_2.extractViewColumns)(fileContent);
53
+ }
54
+ if (extension === '.hdbprocedure') {
55
+ return (0, index_3.extractProcedureParameters)(fileContent);
56
+ }
57
+ if (extension === '.hdbfunction') {
49
58
  return extractProcedureFunctionParameters(fileContent);
50
59
  }
51
60
  return [];
52
61
  }
53
- function extractTableFields(fileContent) {
54
- const subjects = [];
55
- const seen = new Set();
56
- const lines = fileContent.split(/\r?\n/);
57
- const skipKeywords = new Set(['PRIMARY', 'CONSTRAINT', 'UNIQUE', 'FOREIGN', 'CHECK', 'PARTITION', 'INDEX', 'KEY']);
58
- for (const line of lines) {
59
- const trimmedLine = line.trim();
60
- if (trimmedLine.length === 0 || trimmedLine.startsWith('--')) {
61
- continue;
62
- }
63
- const unquotedMatch = trimmedLine.match(/^([A-Za-z_][A-Za-z0-9_]*)\s+[A-Za-z]/);
64
- if (unquotedMatch) {
65
- const candidate = unquotedMatch[1];
66
- if (!candidate) {
67
- continue;
68
- }
69
- if (!skipKeywords.has(candidate.toUpperCase()) && !seen.has(candidate)) {
70
- seen.add(candidate);
71
- subjects.push({ type: 'field', name: candidate });
72
- }
73
- continue;
74
- }
75
- const quotedMatch = trimmedLine.match(/^"([A-Za-z_][A-Za-z0-9_]*)"\s+[A-Za-z]/);
76
- if (quotedMatch) {
77
- const candidate = quotedMatch[1];
78
- if (!candidate) {
79
- continue;
80
- }
81
- if (!seen.has(candidate)) {
82
- seen.add(candidate);
83
- subjects.push({ type: 'field', name: candidate });
84
- }
85
- }
86
- }
87
- return subjects;
88
- }
89
62
  function extractProcedureFunctionParameters(fileContent) {
90
63
  const subjects = [];
91
64
  const seen = new Set();