Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ cdidx mcp # Start MCP server for AI tools
cdidx lsp --db .cdidx/codeindex.db # Start read-only LSP server for editors
```

80 languages supported. 24 registered MCP tools. Incremental updates. Zero config.
82 languages supported. 24 registered MCP tools. Incremental updates. Zero config.

| Topic | Link |
|---|---|
Expand Down Expand Up @@ -1856,6 +1856,8 @@ All indexed languages are searchable through FTS5. Rows with **Symbols = yes** a
| Zig | `.zig` | yes |
| XAML | `.xaml`, `.axaml` | yes |
| MSBuild | `.csproj`, `.fsproj`, `.vbproj`, `.props`, `.targets` | yes |
| Solution | `.sln` | yes |
| Application manifest | `.manifest` | yes |
| Shell | `.sh`, `.bash`, `.zsh`, `.fish` | partial |
| PowerShell | `.ps1`, `.psm1`, `.psd1` | yes |
| Batch | `.bat`, `.cmd` | yes |
Expand Down Expand Up @@ -1894,6 +1896,7 @@ All indexed languages are searchable through FTS5. Rows with **Symbols = yes** a
- JavaScript/TypeScript imports: static imports, dynamic imports, CommonJS `require` / `require.resolve`, `import.meta.resolve`, `new URL(..., import.meta.url)`, `importScripts`, service-worker registrations, worklet loads, and worker constructors add `import` symbols when the specifier is static. `tsconfig.json` / `jsconfig.json` `compilerOptions.baseUrl` and `paths` aliases are resolved to indexed project paths when the target file exists.
- Node module layouts: `.cjs` / `.mjs` are JavaScript; `.cts` / `.mts`, including `.d.cts` / `.d.mts`, are TypeScript.
- Dependency manifests and lockfiles: use `--lang dependency_manifest` or `--lang dependency_lock` for dependency/security audits. These buckets are searchable text and do not claim symbol or graph extraction.
- Solution and application manifests: `.sln` files expose project entries as symbols and project path references; `.manifest` files expose assembly identity, requested execution level, supported OS, and long-path settings as symbols.
- Extensionless scripts: files with recognized shebangs are indexed for shell (`sh`, `bash`, `zsh`, `fish`, `dash`, `ksh`, `ash`), Python, Ruby, Node.js, PHP, Lua, and PowerShell.

### Language extraction matrix
Expand All @@ -1919,6 +1922,7 @@ commands and when to fall back to `search`.
| GLSL / HLSL / Metal / WGSL | entry points, structs, type aliases, resource bindings, constant buffers, samplers, textures, uniforms/inputs/outputs | none yet | Shader entry points and resource declarations are searchable as symbols; use `search` for data-flow, binding compatibility, and call/reference questions. |
| Verilog / SystemVerilog / VHDL | modules, packages, interfaces, classes, functions/tasks/processes, types, signals/parameters | none yet | HDL declarations are available to `symbols`, `definition`, `outline`, and symbol-aware `search`; use plain `search` for netlist/reference questions. |
| Shell / PowerShell / Batch / Makefile / CMake / Justfile / MSBuild / Gradle | functions, labels, targets, recipes, tasks, imports where applicable | command-style calls, target dependencies, and control-flow targets | Runtime command construction is not resolved. |
| Solution / application manifest | solution projects and manifest identity/settings | solution project references; application manifests are symbol-only | `.sln` project paths are graph edges for repository structure; use `symbols --lang app_manifest` for Windows manifest metadata. |
| SQL / Terraform / Dockerfile | statements/resources/stages/labels | table/resource/stage references, Dockerfile stage dependencies, Terraform dotted refs | SQL hotspot grouping defaults to statements; Dockerfile `COPY --from=<stage>` follows named stages. |
| Markdown / HTML / CSS / Sass / Stylus / XAML / GraphQL / Protobuf | headings, anchors, selectors, UI elements, schema types/messages where supported | links/assets/components, local anchors, CSS/Sass/Stylus imports, variables, mixins/functions, XAML resources/bindings/handlers, schema references where supported | Use `search` for prose and generated markup. |
| Dependency manifests / lockfiles | none | none | Use `--lang dependency_manifest` or `--lang dependency_lock` for dependency/security audits. |
Expand Down Expand Up @@ -4400,6 +4404,8 @@ indexing はファイル単位の SQLite transaction を commit します。長
| Zig | `.zig` | yes |
| XAML | `.xaml`, `.axaml` | yes |
| MSBuild | `.csproj`, `.fsproj`, `.vbproj`, `.props`, `.targets` | yes |
| ソリューション | `.sln` | yes |
| アプリケーションマニフェスト | `.manifest` | yes |
| Shell | `.sh`, `.bash`, `.zsh`, `.fish` | partial |
| PowerShell | `.ps1`, `.psm1`, `.psd1` | yes |
| Batch | `.bat`, `.cmd` | yes |
Expand Down Expand Up @@ -4438,6 +4444,7 @@ indexing はファイル単位の SQLite transaction を commit します。長
- JavaScript/TypeScript import: static import、dynamic import、CommonJS `require` / `require.resolve`、`import.meta.resolve`、`new URL(..., import.meta.url)`、`importScripts`、Service Worker registration、worklet load、worker constructor は、specifier が静的なら `import` シンボルを追加します。`tsconfig.json` / `jsconfig.json` の `compilerOptions.baseUrl` と `paths` alias は、対象ファイルが存在する場合に indexed project path へ解決します。
- Node モジュール構成: `.cjs` / `.mjs` は JavaScript、`.cts` / `.mts`(`.d.cts` / `.d.mts` を含む)は TypeScript として扱います。
- Dependency manifest / lockfile: dependency / security audit では `--lang dependency_manifest` または `--lang dependency_lock` を使います。この bucket は検索可能な text として扱われ、symbol / graph 抽出は主張しません。
- ソリューションとアプリケーションマニフェスト: `.sln` は project entry をシンボルとして公開し、project path を参照として記録します。`.manifest` は assembly identity、requested execution level、supported OS、long-path 設定をシンボルとして公開します。
- 拡張子なしスクリプト: 先頭行の shebang が shell (`sh`, `bash`, `zsh`, `fish`, `dash`, `ksh`, `ash`)、Python、Ruby、Node.js、PHP、Lua、PowerShell として認識できれば index 対象です。

### 言語別 extraction matrix
Expand All @@ -4460,6 +4467,7 @@ indexing はファイル単位の SQLite transaction を commit します。長
| GLSL / HLSL / Metal / WGSL | entry point、struct、type alias、resource binding、constant buffer、sampler、texture、uniform/input/output | まだなし | Shader entry point と resource 宣言はシンボルとして検索できます。data-flow、binding compatibility、call/reference の調査には `search` を使ってください。 |
| Verilog / SystemVerilog / VHDL | module、package、interface、class、function/task/process、type、signal/parameter | まだなし | HDL 宣言は `symbols`、`definition`、`outline`、symbol-aware `search` で使えます。netlist / reference の調査には通常の `search` を使ってください。 |
| Shell / PowerShell / Batch / Makefile / CMake / Justfile / MSBuild / Gradle | function、label、target、recipe、task、対応言語の import | command-style call、target dependency、control-flow target | runtime で組み立てられる command は解決しません。 |
| ソリューション / アプリケーションマニフェスト | solution project、manifest identity / setting | `.sln` の project reference。manifest は symbol-only | `.sln` の project path はリポジトリ構造の graph edge です。Windows manifest metadata は `symbols --lang app_manifest` で確認できます。 |
| SQL / Terraform / Dockerfile | statement/resource/stage/label | table/resource/stage reference、Dockerfile stage dependency、Terraform dotted refs | SQL hotspot grouping は既定で statement、Dockerfile `COPY --from=<stage>` は named stage を追跡します。 |
| Markdown / HTML / CSS / Sass / Stylus / XAML / GraphQL / Protobuf | heading、anchor、selector、UI element、対応 schema type/message | link/asset/component、local anchor、CSS/Sass/Stylus の import・variable・mixin/function、XAML resource / binding / handler、対応 schema reference | prose や generated markup には `search` を使ってください。 |
| Dependency manifest / lockfile | なし | なし | dependency / security audit には `--lang dependency_manifest` または `--lang dependency_lock` を使います。 |
Expand Down
26 changes: 26 additions & 0 deletions changelog.d/unreleased/3662.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
category: added
issues:
- 3662
affected:
- src/CodeIndex/Indexer/Scanning/FileIndexer.cs
- src/CodeIndex/Indexer/SolutionFileParser.cs
- src/CodeIndex/Indexer/Symbols/SymbolExtractor.cs
- src/CodeIndex/Indexer/Symbols/SymbolExtractor.StructuralMetadata.cs
- src/CodeIndex/Indexer/References/ReferenceExtractor.Core.cs
- src/CodeIndex/Indexer/References/ReferenceExtractor.State.cs
- src/CodeIndex/Indexer/References/ReferenceExtractor.StructuralMetadata.cs
- src/CodeIndex/Models/SymbolKindCatalog.cs
- tests/CodeIndex.Tests/FileIndexerTests.cs
- tests/CodeIndex.Tests/SymbolExtractorTests.cs
- tests/CodeIndex.Tests/ReferenceExtractorTests.cs
- USER_GUIDE.md
---

## English

- **Solution and application manifest files now have structural extraction (#3662)** — `.sln` files expose project symbols and project-reference edges, while `.manifest` files expose key assembly identity and application compatibility settings as symbols.

## 日本語

- **Solution と application manifest ファイルが構造化抽出に対応しました (#3662)** — `.sln` は project シンボルと project-reference edge を公開し、`.manifest` は主要な assembly identity と application compatibility 設定をシンボルとして公開します。
8 changes: 5 additions & 3 deletions src/CodeIndex/Database/DbReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,15 @@ ELSE 0
// are dependency edges from a lambda body back to an enclosing local and participate in impact.
// C# generic type arguments are retained only when they are attached to an explicit invocation,
// so impact can follow `Process<IFoo>(x)` without promoting ordinary type annotations to
// call-graph edges (#2062).
// call-graph edges (#2062). Solution `project_reference` edges are retained because solution
// files are advertised as graph-supported structural metadata (#3662).
// call-graph (callers/callees/hotspots) に参加する reference kind。`attribute` / `annotation`
// のようなメタデータ kind は非呼び出しエッジなのでここから除外する (issue #293)。
// Razor の `razor_event_binding`、React の `consumes_hook`、C++ の `friend` は依存関係 graph query に含める。
// C# closure の `capture` は lambda 本体から外側 local への依存であり、impact に参加する。
// C# generic invocation type arguments are included when tied to an actual call (#2062).
internal const string CallGraphReferenceKindsSql = "('augmentation', 'call', 'instantiate', 'generic_type_argument', 'subscribe', 'unsubscribe', 'razor_event_binding', 'friend', 'consumes_hook', 'capture')";
// C# generic invocation type arguments are included when tied to an actual call (#2062)。
// solution の `project_reference` は structural metadata として graph 対応を告知しているため含める (#3662)。
internal const string CallGraphReferenceKindsSql = "('augmentation', 'call', 'instantiate', 'generic_type_argument', 'subscribe', 'unsubscribe', 'razor_event_binding', 'friend', 'consumes_hook', 'capture', 'project_reference')";
private const string SyntheticTopLevelCallerName = "<top-level>";
private const string SyntheticTopLevelCallerKind = "function";

Expand Down
3 changes: 3 additions & 0 deletions src/CodeIndex/Indexer/References/ReferenceExtractor.Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ internal static List<ReferenceRecord> ExtractCore(ReferenceExtractionContext req
var typeScriptTypeAliases = language == "typescript"
? TypeScriptReferenceExtractor.BuildTypeAliasTargets(preparedLines)
: null;
if (language == "solution")
return ExtractSolutionReferences(fileId, lines);

var swiftTypeAliases = language == "swift"
? SwiftReferenceExtractor.BuildTypeAliasTargets(preparedLines)
: null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ internal sealed class CSharpWhereConstraintState
"assembly",
"r", "powershell", "shell", "haskell", "solidity",
"gradle", "terraform", "protobuf", "dockerfile", "makefile", "cmake", "justfile", "msbuild",
"solution",
"zig", "css", "sass", "stylus", "xml", "graphql", "html", "markdown", "fortran", "pascal", "objc", "smalltalk"
];

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using CodeIndex.Models;

namespace CodeIndex.Indexer;

public static partial class ReferenceExtractor
{
private static List<ReferenceRecord> ExtractSolutionReferences(long fileId, string[] lines)
{
var references = CreateReferenceList(null);
var seen = new HashSet<string>(StringComparer.Ordinal);
foreach (var project in SolutionFileParser.ExtractProjects(lines))
{
AddReference(
references,
seen,
fileId,
project.NormalizedProjectPath,
project.PathIndex,
"project_reference",
project.Context,
project.LineNumber,
new SymbolRecord
{
Kind = "project",
Name = project.Name,
},
"solution");
}

return references;
}
}
2 changes: 2 additions & 0 deletions src/CodeIndex/Indexer/Scanning/FileIndexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ internal readonly record struct ProjectMarkerFingerprintResult(string? Fingerpri
[".toml"] = "toml",
[".xaml"] = "xml", // WPF/MAUI/Avalonia XAML / XAML テンプレート
[".axaml"] = "xml", // Avalonia XAML / Avalonia XAML
[".sln"] = "solution", // Visual Studio solution / Visual Studio ソリューション
[".manifest"] = "app_manifest", // Windows application manifest / Windows アプリケーションマニフェスト
[".csproj"] = "msbuild",// C# project file / C# プロジェクトファイル
[".fsproj"] = "msbuild",// F# project file / F# プロジェクトファイル
[".vbproj"] = "msbuild",// VB.NET project file / VB.NET プロジェクトファイル
Expand Down
78 changes: 78 additions & 0 deletions src/CodeIndex/Indexer/SolutionFileParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System.Text.RegularExpressions;
using Regex = CodeIndex.Indexer.BoundedRegex;

namespace CodeIndex.Indexer;

internal readonly record struct SolutionProjectEntry(
string Name,
string ProjectPath,
string NormalizedProjectPath,
int LineNumber,
int NameIndex,
int PathIndex,
string Context);

internal static class SolutionFileParser
{
private static readonly Regex ProjectLineRegex = new(
@"^\s*Project\(""(?<typeGuid>[^""]+)""\)\s*=\s*""(?<name>[^""]+)""\s*,\s*""(?<path>[^""]+)""\s*,\s*""(?<projectGuid>[^""]+)""",
RegexOptions.Compiled | RegexOptions.CultureInvariant);

private static readonly HashSet<string> SolutionFolderTypeGuids = new(StringComparer.OrdinalIgnoreCase)
{
"2150E333-8FDC-42A3-9474-1A3956D46DE8",
"66A26720-8FB5-11D2-AA7E-00C04F688DDE",
};

internal static List<SolutionProjectEntry> ExtractProjects(string[] lines)
{
var entries = new List<SolutionProjectEntry>();
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i];
var match = ProjectLineRegex.Match(line);
if (!match.Success)
continue;

var typeGuid = NormalizeGuid(match.Groups["typeGuid"].Value);
if (SolutionFolderTypeGuids.Contains(typeGuid))
continue;

var name = match.Groups["name"].Value.Trim();
var projectPath = match.Groups["path"].Value.Trim();
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(projectPath))
continue;

var normalizedPath = NormalizeProjectPath(projectPath);
if (!IsProjectPath(normalizedPath))
continue;

entries.Add(new SolutionProjectEntry(
name,
projectPath,
normalizedPath,
i + 1,
match.Groups["name"].Index,
match.Groups["path"].Index,
line.Trim()));
}

return entries;
}

private static string NormalizeProjectPath(string projectPath)
=> projectPath.Replace('\\', '/').Trim();

private static string NormalizeGuid(string guid)
=> guid.Trim().Trim('{', '}');

private static bool IsProjectPath(string projectPath)
{
if (string.IsNullOrWhiteSpace(projectPath))
return false;

var fileName = Path.GetFileName(projectPath);
return !string.IsNullOrWhiteSpace(fileName)
&& !string.IsNullOrWhiteSpace(Path.GetExtension(fileName));
}
}
Loading
Loading