@reqlan/language 1.7.0 → 1.8.2

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 (82) hide show
  1. package/README.md +18 -0
  2. package/out/generated/ast.d.ts +28 -1
  3. package/out/generated/ast.js +27 -6
  4. package/out/generated/ast.js.map +1 -1
  5. package/out/generated/grammar.js +1 -1
  6. package/out/generated/grammar.js.map +1 -1
  7. package/out/index.d.ts +1 -0
  8. package/out/index.js +1 -0
  9. package/out/index.js.map +1 -1
  10. package/out/reqlan-code-action-provider.d.ts +15 -12
  11. package/out/reqlan-code-action-provider.js +55 -20
  12. package/out/reqlan-code-action-provider.js.map +1 -1
  13. package/out/reqlan-comment-resolver.js +5 -0
  14. package/out/reqlan-comment-resolver.js.map +1 -1
  15. package/out/reqlan-completion-provider.d.ts +10 -0
  16. package/out/reqlan-completion-provider.js +63 -29
  17. package/out/reqlan-completion-provider.js.map +1 -1
  18. package/out/reqlan-definition-provider.d.ts +7 -0
  19. package/out/reqlan-definition-provider.js +86 -19
  20. package/out/reqlan-definition-provider.js.map +1 -1
  21. package/out/reqlan-document-link-provider.d.ts +2 -1
  22. package/out/reqlan-document-link-provider.js +4 -0
  23. package/out/reqlan-document-link-provider.js.map +1 -1
  24. package/out/reqlan-file-link-resolver.d.ts +17 -4
  25. package/out/reqlan-file-link-resolver.js +89 -14
  26. package/out/reqlan-file-link-resolver.js.map +1 -1
  27. package/out/reqlan-import-edits.d.ts +3 -1
  28. package/out/reqlan-import-edits.js.map +1 -1
  29. package/out/reqlan-inbound-reference-inlay-label.d.ts +11 -0
  30. package/out/reqlan-inbound-reference-inlay-label.js +60 -35
  31. package/out/reqlan-inbound-reference-inlay-label.js.map +1 -1
  32. package/out/reqlan-inlay-hint-provider.d.ts +6 -0
  33. package/out/reqlan-inlay-hint-provider.js +34 -6
  34. package/out/reqlan-inlay-hint-provider.js.map +1 -1
  35. package/out/reqlan-markdown-links.js +4 -0
  36. package/out/reqlan-markdown-links.js.map +1 -1
  37. package/out/reqlan-path-resolve.d.ts +8 -0
  38. package/out/reqlan-path-resolve.js +18 -4
  39. package/out/reqlan-path-resolve.js.map +1 -1
  40. package/out/reqlan-reference-search-site.d.ts +11 -0
  41. package/out/reqlan-reference-search-site.js +11 -0
  42. package/out/reqlan-reference-search-site.js.map +1 -1
  43. package/out/reqlan-scope.d.ts +11 -0
  44. package/out/reqlan-scope.js +28 -1
  45. package/out/reqlan-scope.js.map +1 -1
  46. package/out/reqlan-semantic-token-provider.js +6 -1
  47. package/out/reqlan-semantic-token-provider.js.map +1 -1
  48. package/out/reqlan-token-builder.d.ts +3 -2
  49. package/out/reqlan-token-builder.js +48 -1
  50. package/out/reqlan-token-builder.js.map +1 -1
  51. package/out/reqlan-validator.d.ts +1 -0
  52. package/out/reqlan-validator.js +21 -1
  53. package/out/reqlan-validator.js.map +1 -1
  54. package/out/reqlan-wildcard-resolve.d.ts +45 -0
  55. package/out/reqlan-wildcard-resolve.js +203 -0
  56. package/out/reqlan-wildcard-resolve.js.map +1 -0
  57. package/out/reqlan-workspace-manager.d.ts +7 -0
  58. package/out/reqlan-workspace-manager.js +7 -0
  59. package/out/reqlan-workspace-manager.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/generated/ast.ts +38 -7
  62. package/src/generated/grammar.ts +1 -1
  63. package/src/index.ts +1 -0
  64. package/src/reqlan-code-action-provider.ts +67 -32
  65. package/src/reqlan-comment-resolver.ts +5 -0
  66. package/src/reqlan-completion-provider.ts +81 -27
  67. package/src/reqlan-definition-provider.ts +91 -18
  68. package/src/reqlan-document-link-provider.ts +9 -1
  69. package/src/reqlan-file-link-resolver.ts +112 -17
  70. package/src/reqlan-import-edits.ts +3 -1
  71. package/src/reqlan-inbound-reference-inlay-label.ts +93 -38
  72. package/src/reqlan-inlay-hint-provider.ts +36 -6
  73. package/src/reqlan-markdown-links.ts +4 -0
  74. package/src/reqlan-path-resolve.ts +28 -5
  75. package/src/reqlan-reference-search-site.ts +25 -0
  76. package/src/reqlan-scope.ts +34 -1
  77. package/src/reqlan-semantic-token-provider.ts +6 -0
  78. package/src/reqlan-token-builder.ts +52 -3
  79. package/src/reqlan-validator.ts +34 -0
  80. package/src/reqlan-wildcard-resolve.ts +281 -0
  81. package/src/reqlan-workspace-manager.ts +9 -0
  82. package/src/reqlan.langium +14 -7
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Resolve qualified path + idea-pattern wildcard references.
3
+ * rq:["../../../reqlan rq/language/imports.rq".wildcard_references]
4
+ */
5
+ import type { LangiumDocument, LangiumDocuments } from 'langium';
6
+ import type { Range } from 'vscode-languageserver';
7
+ import { type WildcardReference } from './generated/ast.js';
8
+ import { type PathResolveContext } from './reqlan-path-resolve.js';
9
+ export declare const REQLAN_OPEN_WILDCARD_COMMAND = "reqlan.openWildcardReference";
10
+ export declare const REQLAN_WILDCARD_REFERENCE_AT_REQUEST = "reqlan/wildcardReferenceAt";
11
+ export interface WildcardMatch {
12
+ fileUri: string;
13
+ ideaName: string;
14
+ range?: Range;
15
+ }
16
+ /** Lightweight catalog entry for index-time expansion without full Langium docs. */
17
+ export interface WildcardIdeaCandidate {
18
+ fileUri: string;
19
+ /** Absolute or workspace path used for path-glob matching. */
20
+ filePath: string;
21
+ ideaName: string;
22
+ range?: Range;
23
+ }
24
+ export interface WildcardReferenceArgs {
25
+ pathPattern: string;
26
+ ideaPattern: string;
27
+ fromUri: string;
28
+ }
29
+ export declare function pathHasGlobMeta(path: string): boolean;
30
+ export declare function ideaHasGlobMeta(name: string): boolean;
31
+ /** Convert a shell-style glob to an anchored RegExp. */
32
+ export declare function globToRegExp(glob: string, mode?: 'path' | 'name'): RegExp;
33
+ export declare function wildcardReferenceCommandTarget(args: WildcardReferenceArgs): string;
34
+ export declare function wildcardReferenceLabel(pathPattern: string, ideaPattern: string): string;
35
+ export declare function parseWildcardPathPattern(pathPatternQuoted: string): string;
36
+ /**
37
+ * Resolve the path glob against the document directory / import-root alias,
38
+ * returning a regex that matches absolute file paths (posix-style).
39
+ */
40
+ export declare function pathPatternToAbsoluteRegex(pathPatternQuoted: string, document: LangiumDocument, context?: PathResolveContext): RegExp;
41
+ export declare function collectIdeaCandidatesFromDocuments(documents: Iterable<LangiumDocument>): WildcardIdeaCandidate[];
42
+ export declare function matchWildcardAgainstCatalog(pathPatternQuoted: string, ideaPattern: string, document: LangiumDocument, candidates: readonly WildcardIdeaCandidate[], context?: PathResolveContext): WildcardMatch[];
43
+ export declare function resolveWildcardReferenceMatches(reference: WildcardReference, documents: LangiumDocuments | Iterable<LangiumDocument>, context?: PathResolveContext): WildcardMatch[];
44
+ export declare function wildcardArgsFromReference(reference: WildcardReference): WildcardReferenceArgs;
45
+ export declare function findWildcardReferenceAtPosition(document: LangiumDocument, offset: number): WildcardReference | undefined;
@@ -0,0 +1,203 @@
1
+ import { AstUtils, CstUtils, GrammarUtils, UriUtils } from 'langium';
2
+ import { isIdea, isModel, isOneLinerIdea, isWildcardReference } from './generated/ast.js';
3
+ import { matchImportRootMapping, resolveImportRootUri, resolveRqConfig } from './reqlan-path-resolve.js';
4
+ import { unquoteReqlanString } from './reqlan-quoted-strings.js';
5
+ export const REQLAN_OPEN_WILDCARD_COMMAND = 'reqlan.openWildcardReference';
6
+ export const REQLAN_WILDCARD_REFERENCE_AT_REQUEST = 'reqlan/wildcardReferenceAt';
7
+ export function pathHasGlobMeta(path) {
8
+ return /[*?]/.test(path) || path.includes('**');
9
+ }
10
+ export function ideaHasGlobMeta(name) {
11
+ return /[*?]/.test(name);
12
+ }
13
+ /** Convert a shell-style glob to an anchored RegExp. */
14
+ export function globToRegExp(glob, mode = 'name') {
15
+ let pattern = '';
16
+ for (let i = 0; i < glob.length; i++) {
17
+ const ch = glob[i];
18
+ if (ch === '*' && glob[i + 1] === '*') {
19
+ // ** optionally followed by / matches across path segments
20
+ if (glob[i + 2] === '/') {
21
+ pattern += '(?:.*/)?';
22
+ i += 2;
23
+ }
24
+ else {
25
+ pattern += '.*';
26
+ i += 1;
27
+ }
28
+ continue;
29
+ }
30
+ if (ch === '*') {
31
+ pattern += mode === 'path' ? '[^/]*' : '.*';
32
+ continue;
33
+ }
34
+ if (ch === '?') {
35
+ pattern += mode === 'path' ? '[^/]' : '.';
36
+ continue;
37
+ }
38
+ if ('\\^$+{}[]()|/.'.includes(ch)) {
39
+ pattern += `\\${ch}`;
40
+ continue;
41
+ }
42
+ pattern += ch;
43
+ }
44
+ return new RegExp(`^${pattern}$`);
45
+ }
46
+ export function wildcardReferenceCommandTarget(args) {
47
+ return `command:${REQLAN_OPEN_WILDCARD_COMMAND}?${encodeURIComponent(JSON.stringify([args]))}`;
48
+ }
49
+ export function wildcardReferenceLabel(pathPattern, ideaPattern) {
50
+ return `${pathPattern}.${ideaPattern}`;
51
+ }
52
+ export function parseWildcardPathPattern(pathPatternQuoted) {
53
+ return unquoteReqlanString(pathPatternQuoted);
54
+ }
55
+ /**
56
+ * Resolve the path glob against the document directory / import-root alias,
57
+ * returning a regex that matches absolute file paths (posix-style).
58
+ */
59
+ export function pathPatternToAbsoluteRegex(pathPatternQuoted, document, context) {
60
+ const raw = parseWildcardPathPattern(pathPatternQuoted);
61
+ const config = resolveRqConfig(document, context);
62
+ const matched = matchImportRootMapping(raw, config.importRoots);
63
+ let absoluteGlob;
64
+ if (matched) {
65
+ const importRoot = resolveImportRootUri(document, context, matched.mapping);
66
+ const rootPath = importRoot
67
+ ? uriToPath(importRoot)
68
+ : uriToPath(UriUtils.dirname(document.uri));
69
+ absoluteGlob = joinGlobPath(rootPath, matched.remainder);
70
+ }
71
+ else if (raw.startsWith('/') || /^[A-Za-z]:[\\/]/.test(raw)) {
72
+ absoluteGlob = normalizePathSeparators(raw);
73
+ }
74
+ else {
75
+ absoluteGlob = joinGlobPath(uriToPath(UriUtils.dirname(document.uri)), raw);
76
+ }
77
+ return globToRegExp(normalizePathSeparators(absoluteGlob), 'path');
78
+ }
79
+ export function collectIdeaCandidatesFromDocuments(documents) {
80
+ const candidates = [];
81
+ for (const document of documents) {
82
+ const model = document.parseResult.value;
83
+ if (!isModel(model)) {
84
+ continue;
85
+ }
86
+ const fileUri = document.uri.toString();
87
+ const filePath = uriToPath(document.uri);
88
+ for (const idea of collectIdeas(model)) {
89
+ const nameNode = GrammarUtils.findNodeForProperty(idea.$cstNode, 'name');
90
+ candidates.push({
91
+ fileUri,
92
+ filePath,
93
+ ideaName: idea.name,
94
+ range: nameNode?.range
95
+ });
96
+ }
97
+ }
98
+ return candidates;
99
+ }
100
+ export function matchWildcardAgainstCatalog(pathPatternQuoted, ideaPattern, document, candidates, context) {
101
+ const pathRegex = pathPatternToAbsoluteRegex(pathPatternQuoted, document, context);
102
+ const ideaRegex = globToRegExp(ideaPattern, 'name');
103
+ const matches = [];
104
+ for (const candidate of candidates) {
105
+ const path = normalizePathSeparators(candidate.filePath);
106
+ if (!pathRegex.test(path)) {
107
+ continue;
108
+ }
109
+ if (!ideaRegex.test(candidate.ideaName)) {
110
+ continue;
111
+ }
112
+ matches.push({
113
+ fileUri: candidate.fileUri,
114
+ ideaName: candidate.ideaName,
115
+ range: candidate.range
116
+ });
117
+ }
118
+ return matches.sort((left, right) => {
119
+ const byFile = left.fileUri.localeCompare(right.fileUri);
120
+ return byFile !== 0 ? byFile : left.ideaName.localeCompare(right.ideaName);
121
+ });
122
+ }
123
+ export function resolveWildcardReferenceMatches(reference, documents, context) {
124
+ const document = AstUtils.getDocument(reference);
125
+ const iterable = isLangiumDocuments(documents) ? documents.all : documents;
126
+ const candidates = collectIdeaCandidatesFromDocuments(iterable);
127
+ return matchWildcardAgainstCatalog(reference.pathPattern, reference.ideaPattern, document, candidates, context);
128
+ }
129
+ export function wildcardArgsFromReference(reference) {
130
+ const document = AstUtils.getDocument(reference);
131
+ return {
132
+ pathPattern: parseWildcardPathPattern(reference.pathPattern),
133
+ ideaPattern: reference.ideaPattern,
134
+ fromUri: document.uri.toString()
135
+ };
136
+ }
137
+ export function findWildcardReferenceAtPosition(document, offset) {
138
+ const root = document.parseResult.value.$cstNode;
139
+ if (!root) {
140
+ return undefined;
141
+ }
142
+ let current = CstUtils.findLeafNodeAtOffset(root, offset)?.astNode;
143
+ while (current) {
144
+ if (isWildcardReference(current)) {
145
+ return current;
146
+ }
147
+ if ('target' in current && isWildcardReference(current.target)) {
148
+ return current.target;
149
+ }
150
+ current = current.$container;
151
+ }
152
+ return undefined;
153
+ }
154
+ function collectIdeas(model) {
155
+ const ideas = [];
156
+ for (const node of AstUtils.streamAst(model)) {
157
+ if (isIdea(node) || isOneLinerIdea(node)) {
158
+ ideas.push(node);
159
+ }
160
+ }
161
+ return ideas;
162
+ }
163
+ function isLangiumDocuments(value) {
164
+ return typeof value === 'object' && value !== null && 'all' in value;
165
+ }
166
+ function uriToPath(uri) {
167
+ if (uri.scheme === 'file') {
168
+ return normalizePathSeparators(uri.fsPath ?? uri.path);
169
+ }
170
+ return normalizePathSeparators(uri.path);
171
+ }
172
+ function normalizePathSeparators(path) {
173
+ return path.replace(/\\/g, '/');
174
+ }
175
+ function joinGlobPath(base, relative) {
176
+ const left = normalizePathSeparators(base).replace(/\/+$/, '');
177
+ const right = normalizePathSeparators(relative).replace(/^\/+/, '');
178
+ return normalizeGlobPath(`${left}/${right}`);
179
+ }
180
+ /** Collapse `.` / `..` segments without expanding glob metacharacters. */
181
+ function normalizeGlobPath(path) {
182
+ const absolute = path.startsWith('/');
183
+ const parts = path.split('/');
184
+ const out = [];
185
+ for (const part of parts) {
186
+ if (!part || part === '.') {
187
+ continue;
188
+ }
189
+ if (part === '..') {
190
+ if (out.length > 0 && out[out.length - 1] !== '..' && !/[*?]/.test(out[out.length - 1])) {
191
+ out.pop();
192
+ }
193
+ else if (!absolute) {
194
+ out.push(part);
195
+ }
196
+ continue;
197
+ }
198
+ out.push(part);
199
+ }
200
+ const joined = out.join('/');
201
+ return absolute ? `/${joined}` : joined;
202
+ }
203
+ //# sourceMappingURL=reqlan-wildcard-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reqlan-wildcard-resolve.js","sourceRoot":"","sources":["../src/reqlan-wildcard-resolve.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAO,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE1E,OAAO,EACH,MAAM,EACN,OAAO,EACP,cAAc,EACd,mBAAmB,EAGtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACH,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EAElB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,CAAC,MAAM,4BAA4B,GAAG,8BAA8B,CAAC;AAC3E,MAAM,CAAC,MAAM,oCAAoC,GAAG,4BAA4B,CAAC;AAuBjF,MAAM,UAAU,eAAe,CAAC,IAAY;IACxC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IACxC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAwB,MAAM;IACrE,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACpB,IAAI,EAAE,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACpC,2DAA2D;YAC3D,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACtB,OAAO,IAAI,UAAU,CAAC;gBACtB,CAAC,IAAI,CAAC,CAAC;YACX,CAAC;iBAAM,CAAC;gBACJ,OAAO,IAAI,IAAI,CAAC;gBAChB,CAAC,IAAI,CAAC,CAAC;YACX,CAAC;YACD,SAAS;QACb,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5C,SAAS;QACb,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;YAC1C,SAAS;QACb,CAAC;QACD,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,KAAK,EAAE,EAAE,CAAC;YACrB,SAAS;QACb,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,IAA2B;IACtE,OAAO,WAAW,4BAA4B,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,WAAmB,EAAE,WAAmB;IAC3E,OAAO,GAAG,WAAW,IAAI,WAAW,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,iBAAyB;IAC9D,OAAO,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CACtC,iBAAyB,EACzB,QAAyB,EACzB,OAA4B;IAE5B,MAAM,GAAG,GAAG,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAChE,IAAI,YAAoB,CAAC;IACzB,IAAI,OAAO,EAAE,CAAC;QACV,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,UAAU;YACvB,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC;YACvB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAChD,YAAY,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC;SAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5D,YAAY,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACJ,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,YAAY,CAAC,uBAAuB,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,kCAAkC,CAC9C,SAAoC;IAEpC,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAClB,SAAS;QACb,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzC,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,YAAY,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACzE,UAAU,CAAC,IAAI,CAAC;gBACZ,OAAO;gBACP,QAAQ;gBACR,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,KAAK,EAAE,QAAQ,EAAE,KAAK;aACzB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IACD,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,2BAA2B,CACvC,iBAAyB,EACzB,WAAmB,EACnB,QAAyB,EACzB,UAA4C,EAC5C,OAA4B;IAE5B,MAAM,SAAS,GAAG,0BAA0B,CAAC,iBAAiB,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnF,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACpD,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,GAAG,uBAAuB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,SAAS;QACb,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtC,SAAS;QACb,CAAC;QACD,OAAO,CAAC,IAAI,CAAC;YACT,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,KAAK,EAAE,SAAS,CAAC,KAAK;SACzB,CAAC,CAAC;IACP,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACzD,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC3C,SAA4B,EAC5B,SAAuD,EACvD,OAA4B;IAE5B,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,MAAM,UAAU,GAAG,kCAAkC,CAAC,QAAQ,CAAC,CAAC;IAChE,OAAO,2BAA2B,CAC9B,SAAS,CAAC,WAAW,EACrB,SAAS,CAAC,WAAW,EACrB,QAAQ,EACR,UAAU,EACV,OAAO,CACV,CAAC;AACN,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,SAA4B;IAClE,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACjD,OAAO;QACH,WAAW,EAAE,wBAAwB,CAAC,SAAS,CAAC,WAAW,CAAC;QAC5D,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE;KACnC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC3C,QAAyB,EACzB,MAAc;IAEd,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC;IACjD,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO,SAAS,CAAC;IACrB,CAAC;IACD,IAAI,OAAO,GAAG,QAAQ,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IACnE,OAAO,OAAO,EAAE,CAAC;QACb,IAAI,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,OAAO,OAAO,CAAC;QACnB,CAAC;QACD,IAAI,QAAQ,IAAI,OAAO,IAAI,mBAAmB,CAAE,OAAgC,CAAC,MAAM,CAAC,EAAE,CAAC;YACvF,OAAQ,OAAyC,CAAC,MAAM,CAAC;QAC7D,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,SAAS,YAAY,CAAC,KAA+B;IACjD,MAAM,KAAK,GAAsB,EAAE,CAAC;IACpC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAiD,CAAC,EAAE,CAAC;QACvF,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC;AACzE,CAAC;AAED,SAAS,SAAS,CAAC,GAAQ;IACvB,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,uBAAuB,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,QAAgB;IAChD,MAAM,IAAI,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpE,OAAO,iBAAiB,CAAC,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,0EAA0E;AAC1E,SAAS,iBAAiB,CAAC,IAAY;IACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,SAAS;QACb,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAChB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,EAAE,CAAC;gBACvF,GAAG,CAAC,GAAG,EAAE,CAAC;YACd,CAAC;iBAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;YACD,SAAS;QACb,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAC5C,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { DefaultWorkspaceManager, type LangiumDocument, type LangiumSharedCoreServices, type Stream, type URI } from 'langium';
2
+ import type { RqConfig } from './reqlan-path-resolve.js';
2
3
  /**
3
4
  * Loads workspace documents independently so one catastrophic parse failure
4
5
  * (for example Chevrotain recovery stack overflow) cannot abort LSP workspace init.
@@ -6,6 +7,12 @@ import { DefaultWorkspaceManager, type LangiumDocument, type LangiumSharedCoreSe
6
7
  * rq:["../../../reqlan rq/language/parser_lexer.rq".parse_budget_timeout]
7
8
  */
8
9
  export declare class ReqlanWorkspaceManager extends DefaultWorkspaceManager {
10
+ /**
11
+ * Per-directory cache for resolved `.reqlan/config.json` results.
12
+ * Keyed by directory URI string. `undefined` values mean the directory tree has no `.reqlan/` base.
13
+ * Cleared on workspace reinitialisation so config changes take effect on the next reload.
14
+ */
15
+ readonly rqConfigCache: Map<string, RqConfig | undefined>;
9
16
  constructor(services: LangiumSharedCoreServices);
10
17
  protected loadWorkspaceDocuments(uris: Stream<URI>, collector: (document: LangiumDocument) => void): Promise<void>;
11
18
  }
@@ -8,8 +8,15 @@ import { DefaultWorkspaceManager } from 'langium';
8
8
  export class ReqlanWorkspaceManager extends DefaultWorkspaceManager {
9
9
  constructor(services) {
10
10
  super(services);
11
+ /**
12
+ * Per-directory cache for resolved `.reqlan/config.json` results.
13
+ * Keyed by directory URI string. `undefined` values mean the directory tree has no `.reqlan/` base.
14
+ * Cleared on workspace reinitialisation so config changes take effect on the next reload.
15
+ */
16
+ this.rqConfigCache = new Map();
11
17
  }
12
18
  async loadWorkspaceDocuments(uris, collector) {
19
+ this.rqConfigCache.clear();
13
20
  await Promise.all(uris.map(async (uri) => {
14
21
  try {
15
22
  const document = await this.langiumDocuments.getOrCreateDocument(uri);
@@ -1 +1 @@
1
- {"version":3,"file":"reqlan-workspace-manager.js","sourceRoot":"","sources":["../src/reqlan-workspace-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EAK1B,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,MAAM,OAAO,sBAAuB,SAAQ,uBAAuB;IAC/D,YAAY,QAAmC;QAC3C,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpB,CAAC;IAEkB,KAAK,CAAC,sBAAsB,CAC3C,IAAiB,EACjB,SAA8C;QAE9C,MAAM,OAAO,CAAC,GAAG,CACb,IAAI,CAAC,GAAG,CAAC,KAAK,EAAC,GAAG,EAAC,EAAE;YACjB,IAAI,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;gBACtE,SAAS,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CACT,yEAAyE,GAAG,CAAC,QAAQ,EAAE,EAAE,EACzF,KAAK,CACR,CAAC;YACN,CAAC;QACL,CAAC,CAAC,CACL,CAAC;IACN,CAAC;CACJ"}
1
+ {"version":3,"file":"reqlan-workspace-manager.js","sourceRoot":"","sources":["../src/reqlan-workspace-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EAK1B,MAAM,SAAS,CAAC;AAGjB;;;;;GAKG;AACH,MAAM,OAAO,sBAAuB,SAAQ,uBAAuB;IAQ/D,YAAY,QAAmC;QAC3C,KAAK,CAAC,QAAQ,CAAC,CAAC;QARpB;;;;WAIG;QACM,kBAAa,GAAsC,IAAI,GAAG,EAAE,CAAC;IAItE,CAAC;IAEkB,KAAK,CAAC,sBAAsB,CAC3C,IAAiB,EACjB,SAA8C;QAE9C,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,OAAO,CAAC,GAAG,CACb,IAAI,CAAC,GAAG,CAAC,KAAK,EAAC,GAAG,EAAC,EAAE;YACjB,IAAI,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;gBACtE,SAAS,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CACT,yEAAyE,GAAG,CAAC,QAAQ,EAAE,EAAE,EACzF,KAAK,CACR,CAAC;YACN,CAAC;QACL,CAAC,CAAC,CACL,CAAC;IACN,CAAC;CACJ"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@reqlan/language",
3
3
  "description": "Langium language definition for reqlan (.rq) requirement files",
4
- "version": "1.7.0",
4
+ "version": "1.8.2",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
7
7
  "repository": {
@@ -16,6 +16,7 @@ export namespace Reqlan {
16
16
  SL_COMMENT: /\/\/[^\n\r]*/,
17
17
  MARKDOWN_LINK: /\[(?!\[)[^\]]+\]\([^)]+\)/,
18
18
  ID: /[_a-zA-Z][\w-]*/,
19
+ WILDCARD_NAME: /\*[\w*?-]*|\?[\w*?-]*|[_a-zA-Z][\w-]*[*?][\w*?-]*/,
19
20
  STRING: /"(\\.|[^"\\\r\n])*"|'(\\.|[^'\\\r\n])*'/,
20
21
  NUMBER: /\d+/,
21
22
  WORD: /[A-Za-z_][\w']*/,
@@ -94,6 +95,7 @@ export namespace Reqlan {
94
95
  ScalarValue: ScalarValue
95
96
  TopLevelElement: TopLevelElement
96
97
  WikiLink: WikiLink
98
+ WildcardReference: WildcardReference
97
99
  }
98
100
 
99
101
  }
@@ -514,13 +516,13 @@ export function isInvalidFromImport(item: unknown): item is InvalidFromImport {
514
516
  export type InvalidImportHeadToken = '(' | ')' | '[' | ']' | '`' | 'as' | 'from' | 'import' | '|' | PlainPunctuation | string;
515
517
 
516
518
  export function isInvalidImportHeadToken(item: unknown): item is InvalidImportHeadToken {
517
- return isPlainPunctuation(item) || item === '(' || item === ')' || item === '|' || item === 'as' || item === 'import' || item === 'from' || item === '`' || item === '[' || item === ']' || (typeof item === 'string' && (/[_a-zA-Z][\w-]*/.test(item) || /[A-Za-z_][\w']*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item)));
519
+ return isPlainPunctuation(item) || item === '(' || item === ')' || item === '|' || item === 'as' || item === 'import' || item === 'from' || item === '`' || item === '[' || item === ']' || (typeof item === 'string' && (/[_a-zA-Z][\w-]*/.test(item) || /[A-Za-z_][\w']*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item) || /\*[\w*?-]*|\?[\w*?-]*|[_a-zA-Z][\w-]*[*?][\w*?-]*/.test(item)));
518
520
  }
519
521
 
520
522
  export type InvalidImportToken = '(' | ')' | '[' | ']' | '`' | 'as' | 'from' | 'import' | '|' | PlainPunctuation | string;
521
523
 
522
524
  export function isInvalidImportToken(item: unknown): item is InvalidImportToken {
523
- return isPlainPunctuation(item) || item === '(' || item === ')' || item === '|' || item === 'as' || item === 'import' || item === 'from' || item === '`' || item === '[' || item === ']' || (typeof item === 'string' && (/[_a-zA-Z][\w-]*/.test(item) || /"(\\.|[^"\\\r\n])*"|'(\\.|[^'\\\r\n])*'/.test(item) || /[A-Za-z_][\w']*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item)));
525
+ return isPlainPunctuation(item) || item === '(' || item === ')' || item === '|' || item === 'as' || item === 'import' || item === 'from' || item === '`' || item === '[' || item === ']' || (typeof item === 'string' && (/[_a-zA-Z][\w-]*/.test(item) || /"(\\.|[^"\\\r\n])*"|'(\\.|[^'\\\r\n])*'/.test(item) || /[A-Za-z_][\w']*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item) || /\*[\w*?-]*|\?[\w*?-]*|[_a-zA-Z][\w-]*[*?][\w*?-]*/.test(item)));
524
526
  }
525
527
 
526
528
  export type ListItem = AnonymousBlock | NamedBlockListItem | NestedList | OneLinerListItem;
@@ -557,7 +559,7 @@ export function isListItemPunctuation(item: unknown): item is ListItemPunctuatio
557
559
  export type ListItemText = '(' | '`' | 'as' | 'from' | 'import' | '|' | ListItemPunctuation | string;
558
560
 
559
561
  export function isListItemText(item: unknown): item is ListItemText {
560
- return isListItemPunctuation(item) || item === '(' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /`[^`\n]+`/.test(item) || /[^\s\w\[\]()`]/.test(item)));
562
+ return isListItemPunctuation(item) || item === '(' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /`[^`\n]+`/.test(item) || /[^\s\w\[\]()`]/.test(item) || /\*[\w*?-]*|\?[\w*?-]*|[_a-zA-Z][\w-]*[*?][\w*?-]*/.test(item)));
561
563
  }
562
564
 
563
565
  export interface ListValue extends langium.AstNode {
@@ -726,7 +728,7 @@ export function isNonBangInlineTextPart(item: unknown): item is NonBangInlineTex
726
728
  export type NonBangPlainText = '[' | ']' | '`' | 'as' | 'from' | 'import' | '|' | NonBangPunctuation | string;
727
729
 
728
730
  export function isNonBangPlainText(item: unknown): item is NonBangPlainText {
729
- return isNonBangPunctuation(item) || item === '[' || item === ']' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item)));
731
+ return isNonBangPunctuation(item) || item === '[' || item === ']' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item) || /\*[\w*?-]*|\?[\w*?-]*|[_a-zA-Z][\w-]*[*?][\w*?-]*/.test(item)));
730
732
  }
731
733
 
732
734
  export type NonBangPunctuation = ',' | '-' | '.' | ';' | '?';
@@ -785,7 +787,7 @@ export function isOneLinerListItem(item: unknown): item is OneLinerListItem {
785
787
  export type OneLinerText = '(' | ')' | '`' | 'as' | 'from' | 'import' | '|' | PlainPunctuation | string;
786
788
 
787
789
  export function isOneLinerText(item: unknown): item is OneLinerText {
788
- return isPlainPunctuation(item) || item === '(' || item === ')' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /`[^`\n]+`/.test(item) || /[^\s\w\[\]()`]/.test(item)));
790
+ return isPlainPunctuation(item) || item === '(' || item === ')' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /`[^`\n]+`/.test(item) || /[^\s\w\[\]()`]/.test(item) || /\*[\w*?-]*|\?[\w*?-]*|[_a-zA-Z][\w-]*[*?][\w*?-]*/.test(item)));
789
791
  }
790
792
 
791
793
  export type PlainPunctuation = '!' | ',' | '-' | '.' | ':' | ';' | '?';
@@ -797,7 +799,7 @@ export function isPlainPunctuation(item: unknown): item is PlainPunctuation {
797
799
  export type PlainText = '[' | ']' | '`' | 'as' | 'from' | 'import' | '|' | PlainPunctuation | string;
798
800
 
799
801
  export function isPlainText(item: unknown): item is PlainText {
800
- return isPlainPunctuation(item) || item === '[' || item === ']' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item)));
802
+ return isPlainPunctuation(item) || item === '[' || item === ']' || item === '|' || item === 'from' || item === 'import' || item === 'as' || item === '`' || (typeof item === 'string' && (/[A-Za-z_][\w']*/.test(item) || /[_a-zA-Z][\w-]*/.test(item) || /\d+/.test(item) || /[^\s\w\[\]()`]/.test(item) || /\*[\w*?-]*|\?[\w*?-]*|[_a-zA-Z][\w-]*[*?][\w*?-]*/.test(item)));
801
803
  }
802
804
 
803
805
  export interface QualifiedCommentReference extends langium.AstNode {
@@ -865,7 +867,7 @@ export function isReferenceName(item: unknown): item is ReferenceName {
865
867
  return (typeof item === 'string' && (/[_a-zA-Z][\w-]*/.test(item)));
866
868
  }
867
869
 
868
- export type ReferenceTarget = FileReference | FileSymbolReference | LocalReference | QualifiedReference;
870
+ export type ReferenceTarget = FileReference | FileSymbolReference | LocalReference | QualifiedReference | WildcardReference;
869
871
 
870
872
  export const ReferenceTarget = {
871
873
  $type: 'ReferenceTarget'
@@ -942,6 +944,23 @@ export function isWikiLink(item: unknown): item is WikiLink {
942
944
  return reflection.isInstance(item, WikiLink.$type);
943
945
  }
944
946
 
947
+ export interface WildcardReference extends langium.AstNode {
948
+ readonly $container: BracketReference | WikiLink;
949
+ readonly $type: 'WildcardReference';
950
+ ideaPattern: string;
951
+ pathPattern: string;
952
+ }
953
+
954
+ export const WildcardReference = {
955
+ $type: 'WildcardReference',
956
+ ideaPattern: 'ideaPattern',
957
+ pathPattern: 'pathPattern'
958
+ } as const;
959
+
960
+ export function isWildcardReference(item: unknown): item is WildcardReference {
961
+ return reflection.isInstance(item, WildcardReference.$type);
962
+ }
963
+
945
964
  export class ReqlanAstReflection extends langium.AbstractAstReflection {
946
965
  override readonly types = {
947
966
  AliasPart: {
@@ -1525,6 +1544,18 @@ export class ReqlanAstReflection extends langium.AbstractAstReflection {
1525
1544
  }
1526
1545
  },
1527
1546
  superTypes: [InlineTextPart.$type, NonBangInlineTextPart.$type, RichTextPart.$type]
1547
+ },
1548
+ WildcardReference: {
1549
+ name: WildcardReference.$type,
1550
+ properties: {
1551
+ ideaPattern: {
1552
+ name: WildcardReference.ideaPattern
1553
+ },
1554
+ pathPattern: {
1555
+ name: WildcardReference.pathPattern
1556
+ }
1557
+ },
1558
+ superTypes: [ReferenceTarget.$type]
1528
1559
  }
1529
1560
  } as const satisfies langium.AstMetaData
1530
1561
  }