@c4a/extract-go 0.7.5 → 0.7.8

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 (2) hide show
  1. package/index.js +98 -5
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -12099,6 +12099,44 @@ function functionSignature(node2) {
12099
12099
  function symbolId(filePath, kind, qualifiedName) {
12100
12100
  return `go:${filePath}#${kind}:${qualifiedName}`;
12101
12101
  }
12102
+ function declaredParameters(node2) {
12103
+ if (node2 === null)
12104
+ return [];
12105
+ if (node2.type !== "parameter_list")
12106
+ return [{ name: "", type: node2.text, optional: false, rest: false }];
12107
+ return node2.namedChildren.flatMap((parameter) => {
12108
+ const type = parameter.childForFieldName("type");
12109
+ if (type === null)
12110
+ return [];
12111
+ const names = parameter.namedChildren.filter((child) => child.type === "identifier" && child.id !== type.id);
12112
+ const rest = parameter.type === "variadic_parameter_declaration";
12113
+ return (names.length === 0 ? [""] : names.map((name) => name.text)).map((name) => ({
12114
+ name,
12115
+ type: type.text,
12116
+ optional: rest,
12117
+ rest
12118
+ }));
12119
+ });
12120
+ }
12121
+ function declaredFields(node2, filePath) {
12122
+ const list = node2.namedChildren.find((child) => child.type === "field_declaration_list");
12123
+ return (list?.namedChildren ?? []).flatMap((field) => {
12124
+ if (field.type !== "field_declaration")
12125
+ return [];
12126
+ const type = field.childForFieldName("type");
12127
+ if (type === null)
12128
+ return [];
12129
+ const names = field.namedChildren.filter((child) => child.type === "field_identifier");
12130
+ const tag = field.childForFieldName("tag")?.text;
12131
+ return (names.length === 0 ? [type.text] : names.map((name) => name.text)).map((name) => ({
12132
+ name,
12133
+ type: type.text,
12134
+ embedded: names.length === 0,
12135
+ location: locationFor(filePath, field),
12136
+ ...tag === undefined ? {} : { tag }
12137
+ }));
12138
+ });
12139
+ }
12102
12140
  function extractSymbols(root, filePath, packageName, exportedOnly) {
12103
12141
  const symbols = [];
12104
12142
  for (const node2 of root.namedChildren) {
@@ -12119,6 +12157,8 @@ function extractSymbols(root, filePath, packageName, exportedOnly) {
12119
12157
  ...receiver ? { receiver } : {},
12120
12158
  exported: isExported(name),
12121
12159
  signature: functionSignature(node2),
12160
+ parameters: declaredParameters(node2.childForFieldName("parameters")),
12161
+ results: declaredParameters(node2.childForFieldName("result")),
12122
12162
  ...doc ? { doc } : {},
12123
12163
  location: locationFor(filePath, node2)
12124
12164
  });
@@ -12140,6 +12180,7 @@ function extractSymbols(root, filePath, packageName, exportedOnly) {
12140
12180
  package: packageName,
12141
12181
  exported: isExported(name),
12142
12182
  signature: compact(`type ${name} ${typeNode.text}`),
12183
+ ...kind2 === "struct" ? { fields: declaredFields(typeNode, filePath) } : {},
12143
12184
  ...doc ? { doc } : {},
12144
12185
  location: locationFor(filePath, spec)
12145
12186
  });
@@ -12189,7 +12230,7 @@ function unquoteGoString(value) {
12189
12230
  return trimmed.slice(1, -1);
12190
12231
  }
12191
12232
  }
12192
- function extractImports(root) {
12233
+ function extractImports(root, filePath) {
12193
12234
  const imports = [];
12194
12235
  for (const spec of descendants(root, "import_spec")) {
12195
12236
  const pathNode = spec.childForFieldName("path") ?? spec.namedChildren.find((child) => child.type.endsWith("string_literal"));
@@ -12198,7 +12239,7 @@ function extractImports(root) {
12198
12239
  continue;
12199
12240
  const explicitAlias = spec.childForFieldName("name")?.text;
12200
12241
  const alias = explicitAlias && explicitAlias !== "." && explicitAlias !== "_" ? explicitAlias : importPath.split("/").at(-1) ?? importPath;
12201
- imports.push({ alias, path: importPath });
12242
+ imports.push({ alias, path: importPath, location: locationFor(filePath, spec) });
12202
12243
  }
12203
12244
  return imports.sort((left, right) => left.alias.localeCompare(right.alias) || left.path.localeCompare(right.path));
12204
12245
  }
@@ -12320,7 +12361,7 @@ function indexGoSource(source, filePath, options = {}) {
12320
12361
  throw new Error(`Go parser returned no syntax tree for ${filePath}`);
12321
12362
  const root = tree.rootNode;
12322
12363
  const packageName = descendants(root, "package_identifier")[0]?.text ?? "unknown";
12323
- const imports = extractImports(root);
12364
+ const imports = extractImports(root, filePath);
12324
12365
  const relations = extractCallsAndRoutes(root, filePath, imports);
12325
12366
  return {
12326
12367
  path: filePath,
@@ -12365,6 +12406,18 @@ function symbolInfo(filePath, symbol) {
12365
12406
  line: symbol.location.startLine,
12366
12407
  endLine: symbol.location.endLine,
12367
12408
  signature: symbol.signature,
12409
+ ...symbol.parameters === undefined ? {} : { params: symbol.parameters },
12410
+ ...symbol.results === undefined ? {} : { returnType: symbol.results.map((item) => item.type).join(", ") || null },
12411
+ ...symbol.fields === undefined ? {} : { members: symbol.fields.map((field) => ({
12412
+ name: field.name,
12413
+ kind: "prop" /* Prop */,
12414
+ visibility: /^[A-Z]/u.test(field.name) ? "exported" /* Exported */ : "internal" /* Internal */,
12415
+ file: filePath,
12416
+ line: field.location.startLine,
12417
+ endLine: field.location.endLine,
12418
+ typeAnnotation: field.type,
12419
+ ...field.tag === undefined ? {} : { doc: field.tag }
12420
+ })) },
12368
12421
  ...symbol.doc ? { doc: symbol.doc } : {}
12369
12422
  };
12370
12423
  }
@@ -12432,6 +12485,18 @@ class GoPlugin {
12432
12485
  const indexed = indexGoSource(source, entry.path, { exportedOnly: false });
12433
12486
  files.push({ path: entry.path, language: "go", lines: indexed.lines });
12434
12487
  symbols.push(...indexed.symbols.map((symbol) => symbolInfo(entry.path, symbol)));
12488
+ for (const imported of indexed.imports) {
12489
+ relations.push({
12490
+ type: "imports" /* Imports */,
12491
+ from: entry.path,
12492
+ to: imported.path,
12493
+ isExternal: true,
12494
+ grounding: "code" /* Code */,
12495
+ confidence: 1,
12496
+ source: "ast" /* Ast */,
12497
+ ...imported.location === undefined ? {} : { line: imported.location.startLine }
12498
+ });
12499
+ }
12435
12500
  for (const call of indexed.calls) {
12436
12501
  if (!call.enclosingSymbol)
12437
12502
  continue;
@@ -12454,7 +12519,14 @@ class GoPlugin {
12454
12519
  file: entry.path,
12455
12520
  line: route.location.startLine,
12456
12521
  endLine: route.location.endLine,
12457
- signature: `${route.method} ${route.path} -> ${route.handler}`
12522
+ signature: `${route.method} ${route.path} -> ${route.handler}`,
12523
+ registration: {
12524
+ kind: "http",
12525
+ method: route.method,
12526
+ key: route.path,
12527
+ handler: route.handler,
12528
+ middleware: route.middleware
12529
+ }
12458
12530
  });
12459
12531
  }
12460
12532
  }
@@ -12595,7 +12667,17 @@ var relationSourceSchema = exports_external.enum([
12595
12667
  var packageKindSchema2 = exports_external.enum(Object.values(PackageKind));
12596
12668
  var symbolParamSchema = exports_external.object({
12597
12669
  name: exports_external.string().min(1),
12598
- type: exports_external.string().min(1).nullable()
12670
+ type: exports_external.string().min(1).nullable(),
12671
+ optional: exports_external.boolean().optional(),
12672
+ rest: exports_external.boolean().optional(),
12673
+ defaultValue: exports_external.string().optional()
12674
+ });
12675
+ var registrationSchema = exports_external.object({
12676
+ kind: exports_external.enum(["http", "schedule", "event"]),
12677
+ key: exports_external.string(),
12678
+ handler: exports_external.string(),
12679
+ method: exports_external.string().optional(),
12680
+ middleware: exports_external.array(exports_external.string())
12599
12681
  });
12600
12682
  var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
12601
12683
  name: exports_external.string().min(1),
@@ -12606,6 +12688,14 @@ var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
12606
12688
  endLine: exports_external.number().int().positive(),
12607
12689
  members: exports_external.array(symbolInfoSchema).optional(),
12608
12690
  params: exports_external.array(symbolParamSchema).optional(),
12691
+ optional: exports_external.boolean().optional(),
12692
+ readonly: exports_external.boolean().optional(),
12693
+ defaultValue: exports_external.string().optional(),
12694
+ typeParameters: exports_external.string().optional(),
12695
+ overloads: exports_external.array(exports_external.string()).optional(),
12696
+ publicEntrypoints: exports_external.array(exports_external.string()).optional(),
12697
+ contractResolution: exports_external.enum(["resolved", "declaration-only"]).optional(),
12698
+ registration: registrationSchema.optional(),
12609
12699
  returnType: exports_external.string().min(1).nullable().optional(),
12610
12700
  typeAnnotation: exports_external.string().min(1).nullable().optional(),
12611
12701
  extends: exports_external.string().min(1).nullable().optional(),
@@ -12620,6 +12710,7 @@ var relationInfoSchema = exports_external.object({
12620
12710
  type: relationTypeSchema,
12621
12711
  from: exports_external.string().min(1),
12622
12712
  to: exports_external.string().min(1),
12713
+ file: exports_external.string().min(1).optional(),
12623
12714
  isExternal: exports_external.boolean(),
12624
12715
  grounding: groundingSchema,
12625
12716
  confidence: exports_external.number().min(0).max(1),
@@ -12900,6 +12991,8 @@ function semanticExtractionPayload(extraction) {
12900
12991
  };
12901
12992
  }
12902
12993
  function relationSourceFile(relation, symbols, filePaths) {
12994
+ if (relation.file !== undefined)
12995
+ return filePaths.has(relation.file) ? relation.file : null;
12903
12996
  if (filePaths.has(relation.from))
12904
12997
  return relation.from;
12905
12998
  const candidates = symbols.filter((symbol) => symbol.name === relation.from);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/extract-go",
3
- "version": "0.7.5",
3
+ "version": "0.7.8",
4
4
  "type": "module",
5
5
  "description": "Go extraction plugin and structural index for Context",
6
6
  "license": "MIT",