Skip to content

feat: add Vue support#66

Merged
colbymchenry merged 2 commits into
colbymchenry:mainfrom
abhijeetj100:feat/support-vue
May 8, 2026
Merged

feat: add Vue support#66
colbymchenry merged 2 commits into
colbymchenry:mainfrom
abhijeetj100:feat/support-vue

Conversation

@abhijeetj100
Copy link
Copy Markdown
Contributor

@abhijeetj100 abhijeetj100 commented Mar 25, 2026

This pull request adds comprehensive support for Vue Single-File Components (SFCs) to the code extraction and analysis pipeline. It introduces a new VueExtractor class that can parse .vue files, extract component and function nodes from both standard and <script setup> blocks, and integrate them into the existing code relationship graph. Additionally, the PR updates language detection, grammar support, and framework resolution to recognize and process Vue files throughout the system. Extensive tests are included to verify correct extraction behavior for various Vue SFC patterns.

The most important changes are:

Vue Extraction Support

  • Added a new VueExtractor class to parse .vue files, extract component nodes, delegate script parsing to the TypeScript/JavaScript extractor, and create containment edges between components and their script nodes. This enables accurate modeling of Vue SFCs in the code graph.
  • Updated extractFromSource to use the new VueExtractor when a .vue file is detected, ensuring all Vue files are processed with the appropriate logic.

Language and Grammar Integration

  • Updated language detection, extension mapping, and grammar support to recognize .vue files as the vue language, and ensured all relevant utility functions (e.g., isLanguageSupported, isGrammarLoaded, getSupportedLanguages, getLanguageDisplayName) include vue. [1] [2] [3] [4] [5]

Framework Resolution

  • Added a vueResolver to the framework resolution system and included it in the list of available framework resolvers, enabling Vue-specific relationship resolution. [1] [2] [3]

Testing

  • Added a comprehensive suite of tests for Vue extraction, covering detection, extraction from different script block types, template-only components, and containment relationships between component and script/function nodes.

PS: This is my first contribution to the project. Please let me know if any part of this PR deviates from your established standards—I’m happy to make any necessary adjustments to align with the codebase.

CC: @colbymchenry

Related issue: #51

Conflict resolution after rebasing 6 weeks of main onto this PR:

- src/extraction/tree-sitter.ts: main moved Liquid/Svelte/Dfm extractors
  out of this file into per-extractor modules. Did the same for
  VueExtractor — now lives in src/extraction/vue-extractor.ts. Added
  the import + dispatch line was already present in the PR's diff.
- src/types.ts: main converted Language to a runtime-iterable
  `as const` array (LANGUAGES) for parser/registry use. Kept that
  shape and inserted 'vue' between 'svelte' and 'liquid' so the
  contributor's Vue language work continues to typecheck.
- __tests__/extraction.test.ts: kept both the PR's Vue Extraction
  describe block AND main's new Instantiates+Decorates describe
  block; they don't overlap.
- Removed Sentry's captureException call in the extracted
  VueExtractor — sentry was removed from main, so the import would
  have broken the build.

Verified live on real Vue codebases:
  - vuejs/pinia (36 .vue files): 1,019 nodes, 1,033 edges, no errors
  - vuejs/router (111 .vue files): 3,095 nodes, 2,899 edges, no errors
  Component nodes, script-block extraction, and containment edges all
  produce correct output. Full test suite: 423/423 pass (was 416, +7
  Vue tests).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 8, 2026 02:56
@colbymchenry
Copy link
Copy Markdown
Owner

Reviewed, rebased, and merging — thanks for the contribution, Abhijeet!

Pushed a follow-up commit to your branch resolving the conflicts that accumulated over 6 weeks:

  • src/extraction/tree-sitter.ts had the inline LiquidExtractor/SvelteExtractor/DfmExtractor classes that main has since moved into per-extractor files. Mirrored that for VueExtractor — it now lives in src/extraction/vue-extractor.ts matching the structure of svelte-extractor.ts.
  • src/types.ts was converted to a runtime-iterable LANGUAGES as const array on main; kept that shape and added 'vue' to it.
  • __tests__/extraction.test.ts kept both your Vue Extraction tests and main's new Instantiates+Decorates tests.
  • Removed the captureException call from VueExtractor since Sentry was removed from main.

Validated live on two popular Vue codebases:

  • vuejs/pinia (36 .vue files): 1,019 nodes, 1,033 edges, no errors
  • vuejs/router (111 .vue files): 3,095 nodes, 2,899 edges, no errors

Component nodes, script-block extraction, and containment edges all produce correct output. Full test suite: 423/423 pass (was 416 + your 7 Vue tests).

@colbymchenry colbymchenry merged commit 5ab8174 into colbymchenry:main May 8, 2026
2 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class Vue Single-File Component (SFC) support to the extraction + resolution pipeline so .vue files can participate in the code relationship graph similarly to other frontend component formats (e.g., Svelte).

Changes:

  • Introduces a VueExtractor that delegates <script> / <script setup> parsing to the existing JS/TS tree-sitter extractor and adds component containment edges.
  • Extends language detection / supported-language utilities to recognize .vue as vue and includes .vue in default include globs.
  • Registers a new vueResolver framework resolver (Vue/Nuxt conventions) and adds Vue extraction tests.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/types.ts Adds vue to supported languages and includes **/*.vue in default config globs.
src/resolution/frameworks/vue.ts New Vue/Nuxt framework resolver for macro/auto-import handling and Nuxt route/middleware heuristics.
src/resolution/frameworks/index.ts Registers and re-exports the new vueResolver.
src/extraction/vue-extractor.ts New Vue SFC extractor delegating script parsing to the existing tree-sitter extractor and emitting containment edges.
src/extraction/tree-sitter.ts Routes .vue files to VueExtractor in extractFromSource.
src/extraction/grammars.ts Maps .vue to vue and marks vue as supported via custom extractor path.
tests/extraction.test.ts Adds Vue extraction tests for detection, node creation, and containment edges.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +197 to +201
// Detect Nuxt page routes (pages/ directory)
const pagesIndex = normalized.indexOf('/pages/');
if (pagesIndex !== -1 && normalized.endsWith('.vue')) {
const routePath = filePathToNuxtRoute(normalized, pagesIndex + '/pages/'.length);
if (routePath !== null) {
Comment on lines +282 to +314
const allFiles = context.getAllFiles();
const vueFiles = allFiles.filter((f) => f.endsWith('.vue'));

// Check for exact name match (Button -> Button.vue)
for (const file of vueFiles) {
const fileName = file.split(/[/\\]/).pop() || '';
const componentName = fileName.replace(/\.vue$/, '');
if (componentName === name) {
const nodes = context.getNodesInFile(file);
const component = nodes.find((n) => n.kind === 'component' && n.name === name);
if (component) {
return component.id;
}
}
}

// Check same directory first for better specificity
const fromDir = fromFile.substring(0, fromFile.lastIndexOf('/'));
for (const file of vueFiles) {
if (file.startsWith(fromDir)) {
const fileName = file.split(/[/\\]/).pop() || '';
const componentName = fileName.replace(/\.vue$/, '');
if (componentName === name) {
const nodes = context.getNodesInFile(file);
const component = nodes.find((n) => n.kind === 'component');
if (component) {
return component.id;
}
}
}
}

return null;
Comment on lines +154 to +172
// Delegate to TreeSitterExtractor
const extractor = new TreeSitterExtractor(this.filePath, block.content, scriptLanguage);
const result = extractor.extract();

// Offset line numbers from script block back to .vue file positions
for (const node of result.nodes) {
node.startLine += block.startLine;
node.endLine += block.startLine;
node.language = 'vue'; // Mark as vue, not TS/JS

this.nodes.push(node);

// Add containment edge from component to this node
this.edges.push({
source: componentNodeId,
target: node.id,
kind: 'contains',
});
}
} catch (error) {
this.errors.push({
message: `Vue extraction error: ${error instanceof Error ? error.message : String(error)}`,
severity: 'error',
colbymchenry added a commit to timomeara/codegraph that referenced this pull request May 8, 2026
Conflict resolution after rebasing main onto this PR:

- src/extraction/tree-sitter.ts: main added VueExtractor (new file
  src/extraction/vue-extractor.ts via colbymchenry#66). The PR's restructured
  if/else chain in extractFromSource gets a new vue branch alongside
  svelte/liquid/dfm so the framework-extract pipeline runs uniformly
  for vue files too.
- src/resolution/frameworks/vue.ts: vue resolver still used the dead
  extractNodes(): Node[] interface that this PR replaced. Migrated to
  extract(): { nodes, references } matching the other 13 resolvers —
  Vue's nuxt route detection (pages/, server/api/, middleware/) keeps
  working, just emits no references (matches react.ts shape).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
colbymchenry added a commit that referenced this pull request May 8, 2026
Followup to #66 — Vue support shipped but the README languages table
was never updated.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jorgerobles pushed a commit to jorgerobles/codegraph that referenced this pull request Jun 1, 2026
Co-authored-by: Colby McHenry <me@colbymchenry.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jorgerobles pushed a commit to jorgerobles/codegraph that referenced this pull request Jun 1, 2026
)

Followup to colbymchenry#66 — Vue support shipped but the README languages table
was never updated.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants