@opensip-cli/graph-go 0.1.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 +202 -0
- package/NOTICE +8 -0
- package/README.md +31 -0
- package/dist/__tests__/branch-coverage-2.test.d.ts +21 -0
- package/dist/__tests__/branch-coverage-2.test.d.ts.map +1 -0
- package/dist/__tests__/branch-coverage-2.test.js +187 -0
- package/dist/__tests__/branch-coverage-2.test.js.map +1 -0
- package/dist/__tests__/branch-coverage.test.d.ts +17 -0
- package/dist/__tests__/branch-coverage.test.d.ts.map +1 -0
- package/dist/__tests__/branch-coverage.test.js +136 -0
- package/dist/__tests__/branch-coverage.test.js.map +1 -0
- package/dist/__tests__/cache-key.test.d.ts +5 -0
- package/dist/__tests__/cache-key.test.d.ts.map +1 -0
- package/dist/__tests__/cache-key.test.js +45 -0
- package/dist/__tests__/cache-key.test.js.map +1 -0
- package/dist/__tests__/depends-on-emission.test.d.ts +13 -0
- package/dist/__tests__/depends-on-emission.test.d.ts.map +1 -0
- package/dist/__tests__/depends-on-emission.test.js +215 -0
- package/dist/__tests__/depends-on-emission.test.js.map +1 -0
- package/dist/__tests__/discover.test.d.ts +5 -0
- package/dist/__tests__/discover.test.d.ts.map +1 -0
- package/dist/__tests__/discover.test.js +59 -0
- package/dist/__tests__/discover.test.js.map +1 -0
- package/dist/__tests__/parse.test.d.ts +5 -0
- package/dist/__tests__/parse.test.d.ts.map +1 -0
- package/dist/__tests__/parse.test.js +59 -0
- package/dist/__tests__/parse.test.js.map +1 -0
- package/dist/__tests__/resolve.test.d.ts +18 -0
- package/dist/__tests__/resolve.test.d.ts.map +1 -0
- package/dist/__tests__/resolve.test.js +205 -0
- package/dist/__tests__/resolve.test.js.map +1 -0
- package/dist/__tests__/walk.test.d.ts +10 -0
- package/dist/__tests__/walk.test.d.ts.map +1 -0
- package/dist/__tests__/walk.test.js +163 -0
- package/dist/__tests__/walk.test.js.map +1 -0
- package/dist/body-digest.d.ts +20 -0
- package/dist/body-digest.d.ts.map +1 -0
- package/dist/body-digest.js +139 -0
- package/dist/body-digest.js.map +1 -0
- package/dist/cache-key.d.ts +17 -0
- package/dist/cache-key.d.ts.map +1 -0
- package/dist/cache-key.js +18 -0
- package/dist/cache-key.js.map +1 -0
- package/dist/discover.d.ts +24 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +33 -0
- package/dist/discover.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +17 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +14 -0
- package/dist/parse.js.map +1 -0
- package/dist/resolve.d.ts +32 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +294 -0
- package/dist/resolve.js.map +1 -0
- package/dist/rule-hints.d.ts +16 -0
- package/dist/rule-hints.d.ts.map +1 -0
- package/dist/rule-hints.js +62 -0
- package/dist/rule-hints.js.map +1 -0
- package/dist/walk-metadata.d.ts +22 -0
- package/dist/walk-metadata.d.ts.map +1 -0
- package/dist/walk-metadata.js +96 -0
- package/dist/walk-metadata.js.map +1 -0
- package/dist/walk.d.ts +47 -0
- package/dist/walk.d.ts.map +1 -0
- package/dist/walk.js +278 -0
- package/dist/walk.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go file discovery.
|
|
3
|
+
*
|
|
4
|
+
* Strategy mirrors graph-rust:
|
|
5
|
+
* 1. Locate `go.mod`. We do NOT parse it — recursive `.go` glob with
|
|
6
|
+
* vendor/ excluded handles single modules and most workspace
|
|
7
|
+
* layouts. Go workspace files (`go.work`) listing multiple
|
|
8
|
+
* modules would require parsing; that's a follow-up.
|
|
9
|
+
* 2. If no go.mod present, configPath is undefined; cacheKey falls
|
|
10
|
+
* back to the literal `no-config`.
|
|
11
|
+
* 3. Records go.sum (if present) as the fingerprint — prefers go.sum
|
|
12
|
+
* since it holds the resolved-dep hashes; falls back to go.mod.
|
|
13
|
+
*
|
|
14
|
+
* Excluded directories:
|
|
15
|
+
* - `vendor/` — Go's vendored-dep directory; semantically third-party.
|
|
16
|
+
* - `node_modules/` — rare in Go projects but defensive.
|
|
17
|
+
* - `.git/` — VCS metadata.
|
|
18
|
+
*
|
|
19
|
+
* The collect-loop / realpath-dedup / config-precedence scaffolding lives
|
|
20
|
+
* in `@opensip-cli/graph-adapter-common`; this module supplies only the
|
|
21
|
+
* Go-specific inputs (extension, excludes, config precedence, log tag).
|
|
22
|
+
*/
|
|
23
|
+
export declare const discoverFiles: (input: import("@opensip-cli/graph").DiscoverInput) => import("@opensip-cli/graph").DiscoverOutput;
|
|
24
|
+
//# sourceMappingURL=discover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../src/discover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH,eAAO,MAAM,aAAa,oGAKxB,CAAC"}
|
package/dist/discover.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go file discovery.
|
|
3
|
+
*
|
|
4
|
+
* Strategy mirrors graph-rust:
|
|
5
|
+
* 1. Locate `go.mod`. We do NOT parse it — recursive `.go` glob with
|
|
6
|
+
* vendor/ excluded handles single modules and most workspace
|
|
7
|
+
* layouts. Go workspace files (`go.work`) listing multiple
|
|
8
|
+
* modules would require parsing; that's a follow-up.
|
|
9
|
+
* 2. If no go.mod present, configPath is undefined; cacheKey falls
|
|
10
|
+
* back to the literal `no-config`.
|
|
11
|
+
* 3. Records go.sum (if present) as the fingerprint — prefers go.sum
|
|
12
|
+
* since it holds the resolved-dep hashes; falls back to go.mod.
|
|
13
|
+
*
|
|
14
|
+
* Excluded directories:
|
|
15
|
+
* - `vendor/` — Go's vendored-dep directory; semantically third-party.
|
|
16
|
+
* - `node_modules/` — rare in Go projects but defensive.
|
|
17
|
+
* - `.git/` — VCS metadata.
|
|
18
|
+
*
|
|
19
|
+
* The collect-loop / realpath-dedup / config-precedence scaffolding lives
|
|
20
|
+
* in `@opensip-cli/graph-adapter-common`; this module supplies only the
|
|
21
|
+
* Go-specific inputs (extension, excludes, config precedence, log tag).
|
|
22
|
+
*/
|
|
23
|
+
import { createDiscover } from '@opensip-cli/graph-adapter-common';
|
|
24
|
+
const EXCLUDED_DIR_GLOBS = ['**/vendor/**', '**/node_modules/**', '**/.git/**'];
|
|
25
|
+
// Prefer go.sum (resolved deps with hashes) over go.mod (intent).
|
|
26
|
+
const CONFIG_CANDIDATES = ['go.sum', 'go.mod'];
|
|
27
|
+
export const discoverFiles = createDiscover({
|
|
28
|
+
extension: 'go',
|
|
29
|
+
excludedDirGlobs: EXCLUDED_DIR_GLOBS,
|
|
30
|
+
configCandidates: CONFIG_CANDIDATES,
|
|
31
|
+
languageId: 'go',
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../src/discover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,MAAM,kBAAkB,GAAsB,CAAC,cAAc,EAAE,oBAAoB,EAAE,YAAY,CAAC,CAAC;AAEnG,kEAAkE;AAClE,MAAM,iBAAiB,GAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAElE,MAAM,CAAC,MAAM,aAAa,GAAG,cAAc,CAAC;IAC1C,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,kBAAkB;IACpC,gBAAgB,EAAE,iBAAiB;IACnC,UAAU,EAAE,IAAI;CACjB,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @opensip-cli/graph — Go language adapter.
|
|
3
|
+
*
|
|
4
|
+
* Sibling of graph-rust and graph-python. Backed by tree-sitter-go.
|
|
5
|
+
*
|
|
6
|
+
* Per-rule fidelity: same name-based resolution profile as Python/Rust.
|
|
7
|
+
* Mostly `'medium'` for single-match identifiers; `'low'` for ambiguous
|
|
8
|
+
* matches. The adapter has no symbol table, so method-on-instance,
|
|
9
|
+
* package-qualified call, and free-function call are distinguishable
|
|
10
|
+
* at the AST shape level but cannot be type-narrowed without a real
|
|
11
|
+
* type checker.
|
|
12
|
+
*
|
|
13
|
+
* File layout mirrors graph-rust/:
|
|
14
|
+
* discoverFiles → ./discover.ts (go.mod / go.sum + glob fallback)
|
|
15
|
+
* parseProject → ./parse.ts
|
|
16
|
+
* walkProject → ./walk.ts
|
|
17
|
+
* resolveCallSites → ./resolve.ts
|
|
18
|
+
* cacheKey → ./cache-key.ts (`go-…`)
|
|
19
|
+
* ruleHints → ./rule-hints.ts
|
|
20
|
+
*/
|
|
21
|
+
import { resolveCallSites as goResolveCallSites } from './resolve.js';
|
|
22
|
+
import { walkProject as goWalkProject } from './walk.js';
|
|
23
|
+
export declare const goGraphAdapter: {
|
|
24
|
+
id: string;
|
|
25
|
+
fileExtensions: string[];
|
|
26
|
+
displayName: string;
|
|
27
|
+
discoverFiles: (input: import("@opensip-cli/graph").DiscoverInput) => import("@opensip-cli/graph").DiscoverOutput;
|
|
28
|
+
parseProject: (input: import("@opensip-cli/graph").ParseInput) => import("@opensip-cli/graph").ParseOutput<import("@opensip-cli/graph-adapter-common").TreeSitterParsedProject>;
|
|
29
|
+
walkProject: typeof goWalkProject;
|
|
30
|
+
resolveCallSites: typeof goResolveCallSites;
|
|
31
|
+
cacheKey: (input: import("@opensip-cli/graph").CacheKeyInput) => string;
|
|
32
|
+
ruleHints: import("@opensip-cli/graph").RuleHints;
|
|
33
|
+
};
|
|
34
|
+
/** Plugin discovery contract: exported as `adapter` for runtime registration. */
|
|
35
|
+
export { goGraphAdapter as adapter };
|
|
36
|
+
export declare const metadata: {
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly displayName: string;
|
|
39
|
+
readonly fileExtensions: string[];
|
|
40
|
+
};
|
|
41
|
+
export type { GoParsedProject } from './parse.js';
|
|
42
|
+
export { goRuleHints } from './rule-hints.js';
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAAE,gBAAgB,IAAI,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,MAAM,WAAW,CAAC;AAKzD,eAAO,MAAM,cAAc;;;;;;;;;;CAUsB,CAAC;AAElD,iFAAiF;AACjF,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE,CAAC;AACrC,eAAO,MAAM,QAAQ;;;;CAIX,CAAC;AAEX,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @opensip-cli/graph — Go language adapter.
|
|
3
|
+
*
|
|
4
|
+
* Sibling of graph-rust and graph-python. Backed by tree-sitter-go.
|
|
5
|
+
*
|
|
6
|
+
* Per-rule fidelity: same name-based resolution profile as Python/Rust.
|
|
7
|
+
* Mostly `'medium'` for single-match identifiers; `'low'` for ambiguous
|
|
8
|
+
* matches. The adapter has no symbol table, so method-on-instance,
|
|
9
|
+
* package-qualified call, and free-function call are distinguishable
|
|
10
|
+
* at the AST shape level but cannot be type-narrowed without a real
|
|
11
|
+
* type checker.
|
|
12
|
+
*
|
|
13
|
+
* File layout mirrors graph-rust/:
|
|
14
|
+
* discoverFiles → ./discover.ts (go.mod / go.sum + glob fallback)
|
|
15
|
+
* parseProject → ./parse.ts
|
|
16
|
+
* walkProject → ./walk.ts
|
|
17
|
+
* resolveCallSites → ./resolve.ts
|
|
18
|
+
* cacheKey → ./cache-key.ts (`go-…`)
|
|
19
|
+
* ruleHints → ./rule-hints.ts
|
|
20
|
+
*/
|
|
21
|
+
import { cacheKey as goCacheKey } from './cache-key.js';
|
|
22
|
+
import { discoverFiles as goDiscoverFiles } from './discover.js';
|
|
23
|
+
import { parseProject as goParseProject } from './parse.js';
|
|
24
|
+
import { resolveCallSites as goResolveCallSites } from './resolve.js';
|
|
25
|
+
import { goRuleHints } from './rule-hints.js';
|
|
26
|
+
import { walkProject as goWalkProject } from './walk.js';
|
|
27
|
+
export const goGraphAdapter = {
|
|
28
|
+
id: 'go',
|
|
29
|
+
fileExtensions: ['.go'],
|
|
30
|
+
displayName: 'Go',
|
|
31
|
+
discoverFiles: goDiscoverFiles,
|
|
32
|
+
parseProject: goParseProject,
|
|
33
|
+
walkProject: goWalkProject,
|
|
34
|
+
resolveCallSites: goResolveCallSites,
|
|
35
|
+
cacheKey: goCacheKey,
|
|
36
|
+
ruleHints: goRuleHints,
|
|
37
|
+
};
|
|
38
|
+
/** Plugin discovery contract: exported as `adapter` for runtime registration. */
|
|
39
|
+
export { goGraphAdapter as adapter };
|
|
40
|
+
export const metadata = {
|
|
41
|
+
id: goGraphAdapter.id,
|
|
42
|
+
displayName: goGraphAdapter.displayName,
|
|
43
|
+
fileExtensions: goGraphAdapter.fileExtensions,
|
|
44
|
+
};
|
|
45
|
+
export { goRuleHints } from './rule-hints.js';
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,aAAa,IAAI,eAAe,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,YAAY,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,gBAAgB,IAAI,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,WAAW,IAAI,aAAa,EAAE,MAAM,WAAW,CAAC;AAKzD,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,EAAE,EAAE,IAAI;IACR,cAAc,EAAE,CAAC,KAAK,CAAC;IACvB,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,eAAe;IAC9B,YAAY,EAAE,cAAc;IAC5B,WAAW,EAAE,aAAa;IAC1B,gBAAgB,EAAE,kBAAkB;IACpC,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;CACyB,CAAC;AAElD,iFAAiF;AACjF,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE,CAAC;AACrC,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,EAAE,EAAE,cAAc,CAAC,EAAE;IACrB,WAAW,EAAE,cAAc,CAAC,WAAW;IACvC,cAAc,EAAE,cAAc,CAAC,cAAc;CACrC,CAAC;AAGX,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/parse.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go parseProject — consumes `@opensip-cli/lang-go` (ADR-0010).
|
|
3
|
+
*
|
|
4
|
+
* `lang-go` is the canonical Go parse substrate: it owns the vendored
|
|
5
|
+
* tree-sitter-go grammar and produces the `{ tree, source }` parsed-file shape.
|
|
6
|
+
* The graph adapter no longer loads a grammar of its own; it binds the shared
|
|
7
|
+
* `createParseProjectFromAdapter` driver to `goAdapter`. The parsed-project
|
|
8
|
+
* shape and the downstream walk/resolve are unchanged.
|
|
9
|
+
*/
|
|
10
|
+
import { type TreeSitterParsedFile, type TreeSitterParsedProject } from '@opensip-cli/graph-adapter-common';
|
|
11
|
+
/** Parsed Go source file: tree-sitter parse tree plus original source text. */
|
|
12
|
+
export type GoParsedFile = TreeSitterParsedFile;
|
|
13
|
+
/** Parsed Go project: map of file path → {@link GoParsedFile}. */
|
|
14
|
+
export type GoParsedProject = TreeSitterParsedProject<GoParsedFile>;
|
|
15
|
+
/** Parses every Go source file in the input set into a {@link GoParsedProject}. */
|
|
16
|
+
export declare const parseProject: (input: import("@opensip-cli/graph").ParseInput) => import("@opensip-cli/graph").ParseOutput<TreeSitterParsedProject>;
|
|
17
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC7B,MAAM,mCAAmC,CAAC;AAG3C,+EAA+E;AAC/E,MAAM,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAEhD,kEAAkE;AAClE,MAAM,MAAM,eAAe,GAAG,uBAAuB,CAAC,YAAY,CAAC,CAAC;AAEpE,mFAAmF;AACnF,eAAO,MAAM,YAAY,uHAA2C,CAAC"}
|
package/dist/parse.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go parseProject — consumes `@opensip-cli/lang-go` (ADR-0010).
|
|
3
|
+
*
|
|
4
|
+
* `lang-go` is the canonical Go parse substrate: it owns the vendored
|
|
5
|
+
* tree-sitter-go grammar and produces the `{ tree, source }` parsed-file shape.
|
|
6
|
+
* The graph adapter no longer loads a grammar of its own; it binds the shared
|
|
7
|
+
* `createParseProjectFromAdapter` driver to `goAdapter`. The parsed-project
|
|
8
|
+
* shape and the downstream walk/resolve are unchanged.
|
|
9
|
+
*/
|
|
10
|
+
import { createParseProjectFromAdapter, } from '@opensip-cli/graph-adapter-common';
|
|
11
|
+
import { goAdapter } from '@opensip-cli/lang-go';
|
|
12
|
+
/** Parses every Go source file in the input set into a {@link GoParsedProject}. */
|
|
13
|
+
export const parseProject = createParseProjectFromAdapter(goAdapter);
|
|
14
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,6BAA6B,GAG9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQjD,mFAAmF;AACnF,MAAM,CAAC,MAAM,YAAY,GAAG,6BAA6B,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go resolveCallSites — name-based catalog lookup.
|
|
3
|
+
*
|
|
4
|
+
* Tree-sitter has no symbol table, so we resolve by simple name. For
|
|
5
|
+
* each call site:
|
|
6
|
+
*
|
|
7
|
+
* 1. Decode the called expression. Four shapes matter:
|
|
8
|
+
* - `foo(args)` — identifier; target is `foo`.
|
|
9
|
+
* - `obj.Method(args)` — selector_expression; target is the
|
|
10
|
+
* trailing `field_identifier`.
|
|
11
|
+
* - `pkg.Func(args)` — same shape; AST-indistinguishable
|
|
12
|
+
* from method calls without a type
|
|
13
|
+
* checker. We use the field name.
|
|
14
|
+
* - `Type{}.method(args)` — selector_expression on a
|
|
15
|
+
* composite_literal; we still extract
|
|
16
|
+
* the field name.
|
|
17
|
+
*
|
|
18
|
+
* 2. Look up matching catalog entries by simple name. Confidence
|
|
19
|
+
* ladder mirrors graph-python (no receiver-type narrowing in
|
|
20
|
+
* tree-sitter-go because the receiver type can't be known without
|
|
21
|
+
* type info):
|
|
22
|
+
* - 0 matches → `to: []`, resolution `'unknown'`, confidence `'low'`
|
|
23
|
+
* - 1 match → `to: [hash]`, resolution `'static'`, confidence `'medium'`
|
|
24
|
+
* - N matches → `to: [allHashes]`, resolution `'method-dispatch'`,
|
|
25
|
+
* confidence `'low'`
|
|
26
|
+
*
|
|
27
|
+
* Per I-4: this function does NOT mutate the input catalog.
|
|
28
|
+
*/
|
|
29
|
+
import type { GoParsedProject } from './parse.js';
|
|
30
|
+
import type { ResolveInput, ResolveOutput } from '@opensip-cli/graph';
|
|
31
|
+
export declare function resolveCallSites(input: ResolveInput<GoParsedProject>): ResolveOutput;
|
|
32
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAcH,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAOV,YAAY,EACZ,aAAa,EACd,MAAM,oBAAoB,CAAC;AAkB5B,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,CAAC,eAAe,CAAC,GAAG,aAAa,CAsCpF"}
|
package/dist/resolve.js
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
// @fitness-ignore-file unbounded-memory -- reads single source files at a time during catalog resolution; per-file memory bounded by source size
|
|
2
|
+
/**
|
|
3
|
+
* Go resolveCallSites — name-based catalog lookup.
|
|
4
|
+
*
|
|
5
|
+
* Tree-sitter has no symbol table, so we resolve by simple name. For
|
|
6
|
+
* each call site:
|
|
7
|
+
*
|
|
8
|
+
* 1. Decode the called expression. Four shapes matter:
|
|
9
|
+
* - `foo(args)` — identifier; target is `foo`.
|
|
10
|
+
* - `obj.Method(args)` — selector_expression; target is the
|
|
11
|
+
* trailing `field_identifier`.
|
|
12
|
+
* - `pkg.Func(args)` — same shape; AST-indistinguishable
|
|
13
|
+
* from method calls without a type
|
|
14
|
+
* checker. We use the field name.
|
|
15
|
+
* - `Type{}.method(args)` — selector_expression on a
|
|
16
|
+
* composite_literal; we still extract
|
|
17
|
+
* the field name.
|
|
18
|
+
*
|
|
19
|
+
* 2. Look up matching catalog entries by simple name. Confidence
|
|
20
|
+
* ladder mirrors graph-python (no receiver-type narrowing in
|
|
21
|
+
* tree-sitter-go because the receiver type can't be known without
|
|
22
|
+
* type info):
|
|
23
|
+
* - 0 matches → `to: []`, resolution `'unknown'`, confidence `'low'`
|
|
24
|
+
* - 1 match → `to: [hash]`, resolution `'static'`, confidence `'medium'`
|
|
25
|
+
* - N matches → `to: [allHashes]`, resolution `'method-dispatch'`,
|
|
26
|
+
* confidence `'low'`
|
|
27
|
+
*
|
|
28
|
+
* Per I-4: this function does NOT mutate the input catalog.
|
|
29
|
+
*/
|
|
30
|
+
import { readFileSync } from 'node:fs';
|
|
31
|
+
import { join, posix } from 'node:path';
|
|
32
|
+
import { logger } from '@opensip-cli/core';
|
|
33
|
+
import { appendEdge, createMutableStats, pushCreationEdge, truncateForCallEdge, } from '@opensip-cli/graph';
|
|
34
|
+
import { buildNameIndex } from '@opensip-cli/graph-adapter-common';
|
|
35
|
+
function goPosition(node, file) {
|
|
36
|
+
return {
|
|
37
|
+
line: node.startPosition.row + 1,
|
|
38
|
+
column: node.startPosition.column,
|
|
39
|
+
text: file.source.slice(node.startIndex, node.endIndex),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function resolveCallSites(input) {
|
|
43
|
+
logger.info({ evt: 'graph.edges.start', module: 'graph:edges:go' });
|
|
44
|
+
const byName = buildNameIndex(input.catalog.functions);
|
|
45
|
+
const edgesByOwner = new Map();
|
|
46
|
+
const stats = createMutableStats();
|
|
47
|
+
const sink = { edgesByOwner, stats };
|
|
48
|
+
for (const r of input.callSites) {
|
|
49
|
+
const node = r.nodeRef;
|
|
50
|
+
const file = r.sourceFileRef;
|
|
51
|
+
if (r.kind === 'creation') {
|
|
52
|
+
if (r.childHash === undefined)
|
|
53
|
+
continue;
|
|
54
|
+
pushCreationEdge(goPosition(node, file), r.ownerHash, r.childHash, sink);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
pushCallEdge(node, file, r.ownerHash, byName, sink);
|
|
58
|
+
}
|
|
59
|
+
const finalStats = {
|
|
60
|
+
totalCallSites: stats.totalCallSites,
|
|
61
|
+
resolvedHigh: stats.resolvedHigh,
|
|
62
|
+
resolvedMedium: stats.resolvedMedium,
|
|
63
|
+
resolvedLow: stats.resolvedLow,
|
|
64
|
+
unresolved: stats.unresolved,
|
|
65
|
+
};
|
|
66
|
+
logger.info({ evt: 'graph.edges.complete', module: 'graph:edges:go', ...finalStats });
|
|
67
|
+
// Phase 4 (DEC-498): resolve dependency sites if any. Mirrors the
|
|
68
|
+
// Python adapter's resolveDependencies pattern, adapted to Go's
|
|
69
|
+
// `go.mod`-mediated module-path resolution.
|
|
70
|
+
const dependenciesByOwner = input.dependencySites && input.dependencySites.length > 0
|
|
71
|
+
? resolveDependencies(input.dependencySites, input.catalog, input.projectDirAbs)
|
|
72
|
+
: undefined;
|
|
73
|
+
return dependenciesByOwner === undefined
|
|
74
|
+
? { edgesByOwner, stats: finalStats }
|
|
75
|
+
: { edgesByOwner, dependenciesByOwner, stats: finalStats };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Resolve Go import sites to target module-init bodyHashes. Imports
|
|
79
|
+
* resolving to a same-module source file (via `go.mod`'s declared
|
|
80
|
+
* module path) map to that package directory's module-init occurrences;
|
|
81
|
+
* imports resolving to stdlib (`fmt`, `os`, …), third-party (`github.com/
|
|
82
|
+
* external/lib`), or unresolvable shapes produce unresolved
|
|
83
|
+
* `DependencyEdge` entries with `to: []` and the raw specifier carried
|
|
84
|
+
* in `specifier` for downstream attribution.
|
|
85
|
+
*
|
|
86
|
+
* Resolution rules:
|
|
87
|
+
*
|
|
88
|
+
* 1. Read `go.mod` from `projectDirAbs`. The first `module <path>`
|
|
89
|
+
* line declares the module's own path. If `go.mod` is missing or
|
|
90
|
+
* unparseable, ALL imports go unresolved.
|
|
91
|
+
*
|
|
92
|
+
* 2. Build a `filePath → module-init bodyHash` map from the catalog.
|
|
93
|
+
*
|
|
94
|
+
* 3. For each dependency site, classify the import path:
|
|
95
|
+
* - **Internal** — starts with `<module-path>/` (or equals it):
|
|
96
|
+
* strip the module-path prefix to get a project-relative
|
|
97
|
+
* package-directory path. `to` is every catalog module-init
|
|
98
|
+
* occurrence whose `filePath` lives inside that directory (Go
|
|
99
|
+
* packages can span multiple files — `pkg/foo/foo.go`,
|
|
100
|
+
* `pkg/foo/helpers.go`).
|
|
101
|
+
* - **External** — doesn't start with module path (stdlib like
|
|
102
|
+
* `fmt`, third-party like `github.com/x/y`, or relative-style
|
|
103
|
+
* `./pkg` / `../foo` not common in modern Go): `to: []`.
|
|
104
|
+
*
|
|
105
|
+
* 4. Blank imports (`_ "path"`) and dot imports (`. "path"`) resolve
|
|
106
|
+
* the same as plain imports — the prefix only affects Go's import
|
|
107
|
+
* semantics, not the dependency target.
|
|
108
|
+
*
|
|
109
|
+
* Phase 4 of opensip's substrate consolidation (DEC-498).
|
|
110
|
+
*/
|
|
111
|
+
function resolveDependencies(sites, catalog, projectDirAbs) {
|
|
112
|
+
const modulePath = readGoModulePath(projectDirAbs);
|
|
113
|
+
// Build filePath → module-init bodyHash map. Catalog occurrences carry
|
|
114
|
+
// project-relative POSIX filePath; module-init kind is filtered.
|
|
115
|
+
const moduleInitByFilePath = new Map();
|
|
116
|
+
for (const occs of Object.values(catalog.functions)) {
|
|
117
|
+
if (!occs)
|
|
118
|
+
continue;
|
|
119
|
+
for (const o of occs) {
|
|
120
|
+
if (o.kind === 'module-init')
|
|
121
|
+
moduleInitByFilePath.set(o.filePath, o.bodyHash);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const out = new Map();
|
|
125
|
+
for (const site of sites) {
|
|
126
|
+
const to = resolveGoImportPath(site.specifier, modulePath, moduleInitByFilePath);
|
|
127
|
+
const edge = {
|
|
128
|
+
to,
|
|
129
|
+
line: site.line,
|
|
130
|
+
column: site.column,
|
|
131
|
+
specifier: site.specifier,
|
|
132
|
+
};
|
|
133
|
+
const existing = out.get(site.ownerHash);
|
|
134
|
+
if (existing === undefined) {
|
|
135
|
+
out.set(site.ownerHash, [edge]);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
existing.push(edge);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Extract the module path from `go.mod`. We do a line-grep on `^module
|
|
145
|
+
* <path>$` rather than parse the full grammar — replace directives,
|
|
146
|
+
* vendor blocks, retract statements, and toolchain lines are all
|
|
147
|
+
* out-of-scope for v1. Returns `null` when `go.mod` is missing or no
|
|
148
|
+
* `module` line is found.
|
|
149
|
+
*
|
|
150
|
+
* Edge cases NOT handled (deferred): `replace` directives that retarget
|
|
151
|
+
* a module path, `go.work` multi-module workspaces (each module's own
|
|
152
|
+
* `go.mod` is read independently in this v1).
|
|
153
|
+
*/
|
|
154
|
+
function readGoModulePath(projectDirAbs) {
|
|
155
|
+
let content;
|
|
156
|
+
try {
|
|
157
|
+
content = readFileSync(join(projectDirAbs, 'go.mod'), 'utf8');
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// @fitness-ignore-next-line error-handling-quality -- missing/unreadable go.mod is the expected "no module path" signal for projects that aren't a Go module; caller treats null as "skip module-path resolution".
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
for (const rawLine of content.split('\n')) {
|
|
164
|
+
const line = rawLine.trim();
|
|
165
|
+
// Skip comments and blank lines.
|
|
166
|
+
if (line.length === 0 || line.startsWith('//'))
|
|
167
|
+
continue;
|
|
168
|
+
// `module <path>` — capture the bare path. Quoted form `module "<path>"`
|
|
169
|
+
// is legal in go.mod; strip optional quotes.
|
|
170
|
+
const match = /^module\s+("([^"]+)"|(\S+))\s*$/.exec(line);
|
|
171
|
+
if (match)
|
|
172
|
+
return match[2] ?? match[3] ?? null;
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Resolve one Go import path to its target module-init bodyHash(es).
|
|
178
|
+
* Returns `[]` when the import is external (stdlib, third-party, or
|
|
179
|
+
* unresolvable relative).
|
|
180
|
+
*
|
|
181
|
+
* Multi-file packages: a single import like `"github.com/me/myproj/pkg/foo"`
|
|
182
|
+
* corresponds to the DIRECTORY `pkg/foo/`, which may contain `foo.go`,
|
|
183
|
+
* `helpers.go`, etc. The returned `to` array includes every matching
|
|
184
|
+
* module-init bodyHash — the engine model's polymorphic-targets case.
|
|
185
|
+
*/
|
|
186
|
+
function resolveGoImportPath(specifier, modulePath, moduleInitByFilePath) {
|
|
187
|
+
if (modulePath === null)
|
|
188
|
+
return [];
|
|
189
|
+
// Internal: import path equals or is rooted under the module path.
|
|
190
|
+
if (specifier === modulePath) {
|
|
191
|
+
return collectGoPackageMembers('', moduleInitByFilePath);
|
|
192
|
+
}
|
|
193
|
+
const prefix = `${modulePath}/`;
|
|
194
|
+
if (!specifier.startsWith(prefix))
|
|
195
|
+
return [];
|
|
196
|
+
// The package-directory path is the import path with the module
|
|
197
|
+
// prefix stripped. Forward-slashes are canonical in both go import
|
|
198
|
+
// paths and catalog filePaths.
|
|
199
|
+
const packageDir = specifier.slice(prefix.length);
|
|
200
|
+
return collectGoPackageMembers(packageDir, moduleInitByFilePath);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Enumerate every module-init in the catalog whose filePath sits
|
|
204
|
+
* directly inside `packageDir`. Go's package = directory, with `.go`
|
|
205
|
+
* files at the directory's top level (subdirectories are separate
|
|
206
|
+
* packages). Excludes `_test.go` files from production-import targets?
|
|
207
|
+
* NO — the catalog already carries every walked `.go`, and `_test.go`
|
|
208
|
+
* files belong to the same package directory at the AST level; we
|
|
209
|
+
* include them as edge targets and let downstream rules filter by
|
|
210
|
+
* `inTestFile` if needed.
|
|
211
|
+
*/
|
|
212
|
+
function collectGoPackageMembers(packageDir, moduleInitByFilePath) {
|
|
213
|
+
// packageDir is empty when the module path itself is imported. In
|
|
214
|
+
// that case, the package members live directly at the project root.
|
|
215
|
+
const out = [];
|
|
216
|
+
for (const [filePath, hash] of moduleInitByFilePath) {
|
|
217
|
+
if (!filePath.endsWith('.go'))
|
|
218
|
+
continue;
|
|
219
|
+
const dir = posix.dirname(filePath);
|
|
220
|
+
const normalizedDir = dir === '.' ? '' : dir;
|
|
221
|
+
if (normalizedDir === packageDir)
|
|
222
|
+
out.push(hash);
|
|
223
|
+
}
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
function pushCallEdge(node, file, ownerHash, byName, sink) {
|
|
227
|
+
const { edgesByOwner, stats } = sink;
|
|
228
|
+
stats.totalCallSites++;
|
|
229
|
+
const target = extractCallTargetName(node);
|
|
230
|
+
const pos = goPosition(node, file);
|
|
231
|
+
const truncated = truncateForCallEdge(pos.text);
|
|
232
|
+
const discarded = isReturnValueDiscarded(node);
|
|
233
|
+
const edge = buildGoCallEdge(target, byName, {
|
|
234
|
+
line: pos.line,
|
|
235
|
+
column: pos.column,
|
|
236
|
+
text: truncated,
|
|
237
|
+
discarded,
|
|
238
|
+
});
|
|
239
|
+
appendEdge(edgesByOwner, ownerHash, edge);
|
|
240
|
+
stats.apply(edge);
|
|
241
|
+
}
|
|
242
|
+
function buildGoCallEdge(target, byName, loc) {
|
|
243
|
+
if (target === null) {
|
|
244
|
+
return { to: [], ...loc, resolution: 'unknown', confidence: 'low' };
|
|
245
|
+
}
|
|
246
|
+
const matches = byName.get(target);
|
|
247
|
+
if (!matches || matches.length === 0) {
|
|
248
|
+
return { to: [], ...loc, resolution: 'unknown', confidence: 'low' };
|
|
249
|
+
}
|
|
250
|
+
if (matches.length === 1) {
|
|
251
|
+
return { to: [...matches], ...loc, resolution: 'static', confidence: 'medium' };
|
|
252
|
+
}
|
|
253
|
+
return { to: [...matches], ...loc, resolution: 'method-dispatch', confidence: 'low' };
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Decode a `call_expression` node's target into a simple name. Returns
|
|
257
|
+
* null when we don't recognize the shape (e.g. type assertion call,
|
|
258
|
+
* map index call) — those become unresolved edges.
|
|
259
|
+
*/
|
|
260
|
+
function extractCallTargetName(node) {
|
|
261
|
+
// tree-sitter-go `call_expression` has a `function` field for the callee.
|
|
262
|
+
const fn = node.childForFieldName('function');
|
|
263
|
+
if (!fn)
|
|
264
|
+
return null;
|
|
265
|
+
if (fn.type === 'identifier')
|
|
266
|
+
return fn.text;
|
|
267
|
+
if (fn.type === 'selector_expression') {
|
|
268
|
+
const field = fn.childForFieldName('field');
|
|
269
|
+
return field ? field.text : null;
|
|
270
|
+
}
|
|
271
|
+
// Other shapes (index_expression, parenthesized_expression, etc.) —
|
|
272
|
+
// not common for the call-graph rules we ship today.
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The call's return value is discarded when the call expression is
|
|
277
|
+
* the entire expression of an expression_statement. Go's `go foo()`
|
|
278
|
+
* and `defer foo()` statements also discard the return.
|
|
279
|
+
*/
|
|
280
|
+
function isReturnValueDiscarded(node) {
|
|
281
|
+
let parent = node.parent;
|
|
282
|
+
while (parent) {
|
|
283
|
+
if (parent.type === 'parenthesized_expression') {
|
|
284
|
+
parent = parent.parent;
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
return (parent.type === 'expression_statement' ||
|
|
288
|
+
parent.type === 'go_statement' ||
|
|
289
|
+
parent.type === 'defer_statement');
|
|
290
|
+
}
|
|
291
|
+
/* v8 ignore next */
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go rule hints — language-specific signals for rules.
|
|
3
|
+
*
|
|
4
|
+
* `isTestFile` is file-path-based: Go convention enforces `*_test.go`
|
|
5
|
+
* via the `go test` toolchain, so this predicate is exact for the test
|
|
6
|
+
* concept. No directory convention exists in Go (tests live next to
|
|
7
|
+
* source).
|
|
8
|
+
*
|
|
9
|
+
* Throw-syntax analogue: Go's structural error-propagation is
|
|
10
|
+
* `panic(...)`. The `?` / `try!()` analogue doesn't exist; `return err`
|
|
11
|
+
* is the conventional error path but is too varied syntactically for a
|
|
12
|
+
* regex.
|
|
13
|
+
*/
|
|
14
|
+
import type { RuleHints } from '@opensip-cli/graph';
|
|
15
|
+
export declare const goRuleHints: RuleHints;
|
|
16
|
+
//# sourceMappingURL=rule-hints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-hints.d.ts","sourceRoot":"","sources":["../src/rule-hints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AA8CpD,eAAO,MAAM,WAAW,EAAE,SAKzB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go rule hints — language-specific signals for rules.
|
|
3
|
+
*
|
|
4
|
+
* `isTestFile` is file-path-based: Go convention enforces `*_test.go`
|
|
5
|
+
* via the `go test` toolchain, so this predicate is exact for the test
|
|
6
|
+
* concept. No directory convention exists in Go (tests live next to
|
|
7
|
+
* source).
|
|
8
|
+
*
|
|
9
|
+
* Throw-syntax analogue: Go's structural error-propagation is
|
|
10
|
+
* `panic(...)`. The `?` / `try!()` analogue doesn't exist; `return err`
|
|
11
|
+
* is the conventional error path but is too varied syntactically for a
|
|
12
|
+
* regex.
|
|
13
|
+
*/
|
|
14
|
+
import { isTestFile } from './walk.js';
|
|
15
|
+
const GO_SIDE_EFFECT_PRIMITIVES = [
|
|
16
|
+
'fmt.Print',
|
|
17
|
+
'fmt.Println',
|
|
18
|
+
'fmt.Printf',
|
|
19
|
+
'fmt.Fprint',
|
|
20
|
+
'fmt.Fprintln',
|
|
21
|
+
'fmt.Fprintf',
|
|
22
|
+
'log.Print',
|
|
23
|
+
'log.Println',
|
|
24
|
+
'log.Printf',
|
|
25
|
+
'log.Fatal',
|
|
26
|
+
'log.Fatalln',
|
|
27
|
+
'log.Fatalf',
|
|
28
|
+
'log.Panic',
|
|
29
|
+
'log.Panicln',
|
|
30
|
+
'log.Panicf',
|
|
31
|
+
'os.Exit',
|
|
32
|
+
'os.Setenv',
|
|
33
|
+
'os.Unsetenv',
|
|
34
|
+
'os.Remove',
|
|
35
|
+
'os.RemoveAll',
|
|
36
|
+
'os.Create',
|
|
37
|
+
'os.WriteFile',
|
|
38
|
+
'os.ReadFile',
|
|
39
|
+
'os.Mkdir',
|
|
40
|
+
'os.MkdirAll',
|
|
41
|
+
'time.Sleep',
|
|
42
|
+
'rand.Int',
|
|
43
|
+
'rand.Intn',
|
|
44
|
+
'rand.Float64',
|
|
45
|
+
];
|
|
46
|
+
// Go's structural throw analogue is `panic(...)`. `return err` is also
|
|
47
|
+
// an error path but is too varied to capture via regex.
|
|
48
|
+
const GO_THROW_REGEX = /\bpanic\s*\(/;
|
|
49
|
+
const GO_GENERATED_FILE_PATTERNS = [
|
|
50
|
+
'**/vendor/**',
|
|
51
|
+
'**/*.pb.go',
|
|
52
|
+
'**/*_generated.go',
|
|
53
|
+
'**/*.gen.go',
|
|
54
|
+
'**/zz_generated_*.go',
|
|
55
|
+
];
|
|
56
|
+
export const goRuleHints = {
|
|
57
|
+
isTestFile,
|
|
58
|
+
generatedFilePatterns: GO_GENERATED_FILE_PATTERNS,
|
|
59
|
+
sideEffectPrimitives: GO_SIDE_EFFECT_PRIMITIVES,
|
|
60
|
+
throwSyntaxRegex: GO_THROW_REGEX,
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=rule-hints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-hints.js","sourceRoot":"","sources":["../src/rule-hints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAIvC,MAAM,yBAAyB,GAAsB;IACnD,WAAW;IACX,aAAa;IACb,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,aAAa;IACb,WAAW;IACX,aAAa;IACb,YAAY;IACZ,WAAW;IACX,aAAa;IACb,YAAY;IACZ,WAAW;IACX,aAAa;IACb,YAAY;IACZ,SAAS;IACT,WAAW;IACX,aAAa;IACb,WAAW;IACX,cAAc;IACd,WAAW;IACX,cAAc;IACd,aAAa;IACb,UAAU;IACV,aAAa;IACb,YAAY;IACZ,UAAU;IACV,WAAW;IACX,cAAc;CACf,CAAC;AAEF,uEAAuE;AACvE,wDAAwD;AACxD,MAAM,cAAc,GAAG,cAAc,CAAC;AAEtC,MAAM,0BAA0B,GAAsB;IACpD,cAAc;IACd,YAAY;IACZ,mBAAmB;IACnB,aAAa;IACb,sBAAsB;CACvB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAc;IACpC,UAAU;IACV,qBAAqB,EAAE,0BAA0B;IACjD,oBAAoB,EAAE,yBAAyB;IAC/C,gBAAgB,EAAE,cAAc;CACjC,CAAC"}
|