@c4a/extract-go 0.7.5 → 0.7.9
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/index.js +128 -23
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -11444,15 +11444,21 @@ function replaceWithCount(value, pattern, replacement, count) {
|
|
|
11444
11444
|
return replacement(...args.slice(0, -2));
|
|
11445
11445
|
});
|
|
11446
11446
|
}
|
|
11447
|
+
var SECRET_TEXT_KEY = "(?:[A-Za-z0-9_.-]*(?:password|passwd|pwd|secret|token|credential|cookie)[A-Za-z0-9_.-]*|api[-_]?key|access[-_]?(?:key|token)|private[-_]?key|client[-_]?secret|authorization)";
|
|
11448
|
+
var SECRET_TEXT_ASSIGNMENT = `(?:=\\s*|:\\s+(?=\\S)|:\\s*(?=["']))`;
|
|
11449
|
+
var AUTHORIZATION_TEXT_PATTERN = new RegExp(`(\\bauthorization\\s*:\\s*(?:bearer|basic)\\s+)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^\\s,;]+`, "giu");
|
|
11450
|
+
var QUERY_SECRET_TEXT_PATTERN = new RegExp(`([?&](?:access_token|refresh_token|api_key|password|secret)=)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^&#\\s]+`, "giu");
|
|
11451
|
+
var ASSIGNMENT_SECRET_TEXT_PATTERN = new RegExp(`((?:["']?${SECRET_TEXT_KEY}["']?)\\s*${SECRET_TEXT_ASSIGNMENT})` + `(?!["']?${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})` + `(?:"(?:\\\\.|[^"])*"|'(?:\\\\.|[^'])*'|[^\\s,;}\\]]+)`, "giu");
|
|
11447
11452
|
function redactKnownText(value, count) {
|
|
11453
|
+
if (!value.includes(":") && !value.includes("=") && !value.includes("-----BEGIN ")) {
|
|
11454
|
+
return value;
|
|
11455
|
+
}
|
|
11448
11456
|
let output = value;
|
|
11449
11457
|
output = replaceWithCount(output, /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/gu, INDEXER_OUTPUT_REDACTION_MARKER, count);
|
|
11450
|
-
output = replaceWithCount(output,
|
|
11458
|
+
output = replaceWithCount(output, AUTHORIZATION_TEXT_PATTERN, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
|
|
11451
11459
|
output = replaceWithCount(output, /([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/giu, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}@`, count);
|
|
11452
|
-
output = replaceWithCount(output,
|
|
11453
|
-
|
|
11454
|
-
const assignment = `(?:=\\s*|:\\s+(?=\\S)|:\\s*(?=["']))`;
|
|
11455
|
-
output = replaceWithCount(output, new RegExp(`((?:["']?${key}["']?)\\s*${assignment})` + `(?!["']?${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})` + `(?:"(?:\\\\.|[^"])*"|'(?:\\\\.|[^'])*'|[^\\s,;}\\]]+)`, "giu"), (_match, prefix) => `${prefix}"${INDEXER_OUTPUT_REDACTION_MARKER}"`, count);
|
|
11460
|
+
output = replaceWithCount(output, QUERY_SECRET_TEXT_PATTERN, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
|
|
11461
|
+
output = replaceWithCount(output, ASSIGNMENT_SECRET_TEXT_PATTERN, (_match, prefix) => `${prefix}"${INDEXER_OUTPUT_REDACTION_MARKER}"`, count);
|
|
11456
11462
|
return output;
|
|
11457
11463
|
}
|
|
11458
11464
|
function redactBlockedText(value, blocked, count) {
|
|
@@ -12099,6 +12105,44 @@ function functionSignature(node2) {
|
|
|
12099
12105
|
function symbolId(filePath, kind, qualifiedName) {
|
|
12100
12106
|
return `go:${filePath}#${kind}:${qualifiedName}`;
|
|
12101
12107
|
}
|
|
12108
|
+
function declaredParameters(node2) {
|
|
12109
|
+
if (node2 === null)
|
|
12110
|
+
return [];
|
|
12111
|
+
if (node2.type !== "parameter_list")
|
|
12112
|
+
return [{ name: "", type: node2.text, optional: false, rest: false }];
|
|
12113
|
+
return node2.namedChildren.flatMap((parameter) => {
|
|
12114
|
+
const type = parameter.childForFieldName("type");
|
|
12115
|
+
if (type === null)
|
|
12116
|
+
return [];
|
|
12117
|
+
const names = parameter.namedChildren.filter((child) => child.type === "identifier" && child.id !== type.id);
|
|
12118
|
+
const rest = parameter.type === "variadic_parameter_declaration";
|
|
12119
|
+
return (names.length === 0 ? [""] : names.map((name) => name.text)).map((name) => ({
|
|
12120
|
+
name,
|
|
12121
|
+
type: type.text,
|
|
12122
|
+
optional: rest,
|
|
12123
|
+
rest
|
|
12124
|
+
}));
|
|
12125
|
+
});
|
|
12126
|
+
}
|
|
12127
|
+
function declaredFields(node2, filePath) {
|
|
12128
|
+
const list = node2.namedChildren.find((child) => child.type === "field_declaration_list");
|
|
12129
|
+
return (list?.namedChildren ?? []).flatMap((field) => {
|
|
12130
|
+
if (field.type !== "field_declaration")
|
|
12131
|
+
return [];
|
|
12132
|
+
const type = field.childForFieldName("type");
|
|
12133
|
+
if (type === null)
|
|
12134
|
+
return [];
|
|
12135
|
+
const names = field.namedChildren.filter((child) => child.type === "field_identifier");
|
|
12136
|
+
const tag = field.childForFieldName("tag")?.text;
|
|
12137
|
+
return (names.length === 0 ? [type.text] : names.map((name) => name.text)).map((name) => ({
|
|
12138
|
+
name,
|
|
12139
|
+
type: type.text,
|
|
12140
|
+
embedded: names.length === 0,
|
|
12141
|
+
location: locationFor(filePath, field),
|
|
12142
|
+
...tag === undefined ? {} : { tag }
|
|
12143
|
+
}));
|
|
12144
|
+
});
|
|
12145
|
+
}
|
|
12102
12146
|
function extractSymbols(root, filePath, packageName, exportedOnly) {
|
|
12103
12147
|
const symbols = [];
|
|
12104
12148
|
for (const node2 of root.namedChildren) {
|
|
@@ -12119,6 +12163,8 @@ function extractSymbols(root, filePath, packageName, exportedOnly) {
|
|
|
12119
12163
|
...receiver ? { receiver } : {},
|
|
12120
12164
|
exported: isExported(name),
|
|
12121
12165
|
signature: functionSignature(node2),
|
|
12166
|
+
parameters: declaredParameters(node2.childForFieldName("parameters")),
|
|
12167
|
+
results: declaredParameters(node2.childForFieldName("result")),
|
|
12122
12168
|
...doc ? { doc } : {},
|
|
12123
12169
|
location: locationFor(filePath, node2)
|
|
12124
12170
|
});
|
|
@@ -12140,6 +12186,7 @@ function extractSymbols(root, filePath, packageName, exportedOnly) {
|
|
|
12140
12186
|
package: packageName,
|
|
12141
12187
|
exported: isExported(name),
|
|
12142
12188
|
signature: compact(`type ${name} ${typeNode.text}`),
|
|
12189
|
+
...kind2 === "struct" ? { fields: declaredFields(typeNode, filePath) } : {},
|
|
12143
12190
|
...doc ? { doc } : {},
|
|
12144
12191
|
location: locationFor(filePath, spec)
|
|
12145
12192
|
});
|
|
@@ -12189,7 +12236,7 @@ function unquoteGoString(value) {
|
|
|
12189
12236
|
return trimmed.slice(1, -1);
|
|
12190
12237
|
}
|
|
12191
12238
|
}
|
|
12192
|
-
function extractImports(root) {
|
|
12239
|
+
function extractImports(root, filePath) {
|
|
12193
12240
|
const imports = [];
|
|
12194
12241
|
for (const spec of descendants(root, "import_spec")) {
|
|
12195
12242
|
const pathNode = spec.childForFieldName("path") ?? spec.namedChildren.find((child) => child.type.endsWith("string_literal"));
|
|
@@ -12198,7 +12245,7 @@ function extractImports(root) {
|
|
|
12198
12245
|
continue;
|
|
12199
12246
|
const explicitAlias = spec.childForFieldName("name")?.text;
|
|
12200
12247
|
const alias = explicitAlias && explicitAlias !== "." && explicitAlias !== "_" ? explicitAlias : importPath.split("/").at(-1) ?? importPath;
|
|
12201
|
-
imports.push({ alias, path: importPath });
|
|
12248
|
+
imports.push({ alias, path: importPath, location: locationFor(filePath, spec) });
|
|
12202
12249
|
}
|
|
12203
12250
|
return imports.sort((left, right) => left.alias.localeCompare(right.alias) || left.path.localeCompare(right.path));
|
|
12204
12251
|
}
|
|
@@ -12318,20 +12365,24 @@ function indexGoSource(source, filePath, options = {}) {
|
|
|
12318
12365
|
const tree = parser.parse(source);
|
|
12319
12366
|
if (!tree)
|
|
12320
12367
|
throw new Error(`Go parser returned no syntax tree for ${filePath}`);
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
|
|
12333
|
-
|
|
12334
|
-
|
|
12368
|
+
try {
|
|
12369
|
+
const root = tree.rootNode;
|
|
12370
|
+
const packageName = descendants(root, "package_identifier")[0]?.text ?? "unknown";
|
|
12371
|
+
const imports = extractImports(root, filePath);
|
|
12372
|
+
const relations = extractCallsAndRoutes(root, filePath, imports);
|
|
12373
|
+
return {
|
|
12374
|
+
path: filePath,
|
|
12375
|
+
package: packageName,
|
|
12376
|
+
imports,
|
|
12377
|
+
symbols: extractSymbols(root, filePath, packageName, options.exportedOnly ?? false),
|
|
12378
|
+
calls: relations.calls,
|
|
12379
|
+
routes: relations.routes,
|
|
12380
|
+
parseErrors: countParseErrors(root),
|
|
12381
|
+
lines: source.length === 0 ? 0 : source.split(/\r\n|\r|\n/u).length
|
|
12382
|
+
};
|
|
12383
|
+
} finally {
|
|
12384
|
+
tree.delete();
|
|
12385
|
+
}
|
|
12335
12386
|
}
|
|
12336
12387
|
|
|
12337
12388
|
// src/plugin.ts
|
|
@@ -12365,6 +12416,18 @@ function symbolInfo(filePath, symbol) {
|
|
|
12365
12416
|
line: symbol.location.startLine,
|
|
12366
12417
|
endLine: symbol.location.endLine,
|
|
12367
12418
|
signature: symbol.signature,
|
|
12419
|
+
...symbol.parameters === undefined ? {} : { params: symbol.parameters },
|
|
12420
|
+
...symbol.results === undefined ? {} : { returnType: symbol.results.map((item) => item.type).join(", ") || null },
|
|
12421
|
+
...symbol.fields === undefined ? {} : { members: symbol.fields.map((field) => ({
|
|
12422
|
+
name: field.name,
|
|
12423
|
+
kind: "prop" /* Prop */,
|
|
12424
|
+
visibility: /^[A-Z]/u.test(field.name) ? "exported" /* Exported */ : "internal" /* Internal */,
|
|
12425
|
+
file: filePath,
|
|
12426
|
+
line: field.location.startLine,
|
|
12427
|
+
endLine: field.location.endLine,
|
|
12428
|
+
typeAnnotation: field.type,
|
|
12429
|
+
...field.tag === undefined ? {} : { doc: field.tag }
|
|
12430
|
+
})) },
|
|
12368
12431
|
...symbol.doc ? { doc: symbol.doc } : {}
|
|
12369
12432
|
};
|
|
12370
12433
|
}
|
|
@@ -12432,12 +12495,26 @@ class GoPlugin {
|
|
|
12432
12495
|
const indexed = indexGoSource(source, entry.path, { exportedOnly: false });
|
|
12433
12496
|
files.push({ path: entry.path, language: "go", lines: indexed.lines });
|
|
12434
12497
|
symbols.push(...indexed.symbols.map((symbol) => symbolInfo(entry.path, symbol)));
|
|
12498
|
+
for (const imported of indexed.imports) {
|
|
12499
|
+
relations.push({
|
|
12500
|
+
type: "imports" /* Imports */,
|
|
12501
|
+
from: entry.path,
|
|
12502
|
+
file: entry.path,
|
|
12503
|
+
to: imported.path,
|
|
12504
|
+
isExternal: true,
|
|
12505
|
+
grounding: "code" /* Code */,
|
|
12506
|
+
confidence: 1,
|
|
12507
|
+
source: "ast" /* Ast */,
|
|
12508
|
+
...imported.location === undefined ? {} : { line: imported.location.startLine }
|
|
12509
|
+
});
|
|
12510
|
+
}
|
|
12435
12511
|
for (const call of indexed.calls) {
|
|
12436
12512
|
if (!call.enclosingSymbol)
|
|
12437
12513
|
continue;
|
|
12438
12514
|
relations.push({
|
|
12439
12515
|
type: "calls" /* Calls */,
|
|
12440
12516
|
from: call.enclosingSymbol,
|
|
12517
|
+
file: entry.path,
|
|
12441
12518
|
to: call.callee,
|
|
12442
12519
|
isExternal: call.importPath !== undefined,
|
|
12443
12520
|
grounding: "code" /* Code */,
|
|
@@ -12454,7 +12531,14 @@ class GoPlugin {
|
|
|
12454
12531
|
file: entry.path,
|
|
12455
12532
|
line: route.location.startLine,
|
|
12456
12533
|
endLine: route.location.endLine,
|
|
12457
|
-
signature: `${route.method} ${route.path} -> ${route.handler}
|
|
12534
|
+
signature: `${route.method} ${route.path} -> ${route.handler}`,
|
|
12535
|
+
registration: {
|
|
12536
|
+
kind: "http",
|
|
12537
|
+
method: route.method,
|
|
12538
|
+
key: route.path,
|
|
12539
|
+
handler: route.handler,
|
|
12540
|
+
middleware: route.middleware
|
|
12541
|
+
}
|
|
12458
12542
|
});
|
|
12459
12543
|
}
|
|
12460
12544
|
}
|
|
@@ -12595,7 +12679,17 @@ var relationSourceSchema = exports_external.enum([
|
|
|
12595
12679
|
var packageKindSchema2 = exports_external.enum(Object.values(PackageKind));
|
|
12596
12680
|
var symbolParamSchema = exports_external.object({
|
|
12597
12681
|
name: exports_external.string().min(1),
|
|
12598
|
-
type: exports_external.string().min(1).nullable()
|
|
12682
|
+
type: exports_external.string().min(1).nullable(),
|
|
12683
|
+
optional: exports_external.boolean().optional(),
|
|
12684
|
+
rest: exports_external.boolean().optional(),
|
|
12685
|
+
defaultValue: exports_external.string().optional()
|
|
12686
|
+
});
|
|
12687
|
+
var registrationSchema = exports_external.object({
|
|
12688
|
+
kind: exports_external.enum(["http", "schedule", "event"]),
|
|
12689
|
+
key: exports_external.string(),
|
|
12690
|
+
handler: exports_external.string(),
|
|
12691
|
+
method: exports_external.string().optional(),
|
|
12692
|
+
middleware: exports_external.array(exports_external.string())
|
|
12599
12693
|
});
|
|
12600
12694
|
var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
|
|
12601
12695
|
name: exports_external.string().min(1),
|
|
@@ -12606,6 +12700,14 @@ var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
|
|
|
12606
12700
|
endLine: exports_external.number().int().positive(),
|
|
12607
12701
|
members: exports_external.array(symbolInfoSchema).optional(),
|
|
12608
12702
|
params: exports_external.array(symbolParamSchema).optional(),
|
|
12703
|
+
optional: exports_external.boolean().optional(),
|
|
12704
|
+
readonly: exports_external.boolean().optional(),
|
|
12705
|
+
defaultValue: exports_external.string().optional(),
|
|
12706
|
+
typeParameters: exports_external.string().optional(),
|
|
12707
|
+
overloads: exports_external.array(exports_external.string()).optional(),
|
|
12708
|
+
publicEntrypoints: exports_external.array(exports_external.string()).optional(),
|
|
12709
|
+
contractResolution: exports_external.enum(["resolved", "declaration-only"]).optional(),
|
|
12710
|
+
registration: registrationSchema.optional(),
|
|
12609
12711
|
returnType: exports_external.string().min(1).nullable().optional(),
|
|
12610
12712
|
typeAnnotation: exports_external.string().min(1).nullable().optional(),
|
|
12611
12713
|
extends: exports_external.string().min(1).nullable().optional(),
|
|
@@ -12620,6 +12722,7 @@ var relationInfoSchema = exports_external.object({
|
|
|
12620
12722
|
type: relationTypeSchema,
|
|
12621
12723
|
from: exports_external.string().min(1),
|
|
12622
12724
|
to: exports_external.string().min(1),
|
|
12725
|
+
file: exports_external.string().min(1).optional(),
|
|
12623
12726
|
isExternal: exports_external.boolean(),
|
|
12624
12727
|
grounding: groundingSchema,
|
|
12625
12728
|
confidence: exports_external.number().min(0).max(1),
|
|
@@ -12900,6 +13003,8 @@ function semanticExtractionPayload(extraction) {
|
|
|
12900
13003
|
};
|
|
12901
13004
|
}
|
|
12902
13005
|
function relationSourceFile(relation, symbols, filePaths) {
|
|
13006
|
+
if (relation.file !== undefined)
|
|
13007
|
+
return filePaths.has(relation.file) ? relation.file : null;
|
|
12903
13008
|
if (filePaths.has(relation.from))
|
|
12904
13009
|
return relation.from;
|
|
12905
13010
|
const candidates = symbols.filter((symbol) => symbol.name === relation.from);
|