fix: resolve codebase indexing ignore rules issues (#5655)

- Fix .gitignore files having no effect on indexing by replacing broken single-file logic with proper findGitignoreFiles() usage
- Fix .rooignore inconsistency by using global RooIgnoreController instance instead of creating new instances per scan
- Fix .rooignore rules being ignored after 'Clear Index Data' by ensuring patterns are reloaded during service recreation
- Add comprehensive integration tests covering all three reported issues
- Fix VSCode test mocks to support RelativePattern and createFileSystemWatcher
- Ensure backward compatibility and proper disposal handling

All 346 code-index tests passing with new integration test coverage.
This commit is contained in:
Roo Code 2025-07-13 10:22:12 +00:00
parent e84dd0a2cf
commit d38a99671f
7 changed files with 591 additions and 19 deletions

View file

@ -60,7 +60,7 @@ export class RooIgnoreController {
/**
* Load custom patterns from .rooignore if it exists
*/
private async loadRooIgnore(): Promise<void> {
public async loadRooIgnore(): Promise<void> {
try {
// Reset ignore instance to prevent duplicate patterns
this.ignoreInstance = ignore()
@ -183,7 +183,7 @@ export class RooIgnoreController {
* Clean up resources when the controller is no longer needed
*/
dispose(): void {
this.disposables.forEach((d) => d.dispose())
this.disposables.forEach((d) => d?.dispose?.())
this.disposables = []
}

View file

@ -0,0 +1,492 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
import { CodeIndexManager } from "../manager"
import { CodeIndexServiceFactory } from "../service-factory"
import type { MockedClass } from "vitest"
import fs from "fs/promises"
import path from "path"
// Mock vscode module
vi.mock("vscode", () => ({
workspace: {
workspaceFolders: [
{
uri: { fsPath: "/test/workspace" },
name: "test",
index: 0,
},
],
createFileSystemWatcher: vi.fn(() => ({
onDidCreate: vi.fn(),
onDidChange: vi.fn(),
onDidDelete: vi.fn(),
dispose: vi.fn(),
})),
},
RelativePattern: vi.fn().mockImplementation((base, pattern) => ({
base,
pattern,
})),
}))
// Mock path utilities
vi.mock("../../../utils/path", () => ({
getWorkspacePath: vi.fn(() => "/test/workspace"),
}))
// Mock fs operations
vi.mock("fs/promises")
const mockFs = fs as any
// Mock file existence check
vi.mock("../../../utils/fs", () => ({
fileExistsAtPath: vi.fn(),
}))
// Mock glob utilities
vi.mock("../../glob/list-files", () => ({
findGitignoreFiles: vi.fn(),
}))
// Mock state manager
vi.mock("../state-manager", () => ({
CodeIndexStateManager: vi.fn().mockImplementation(() => ({
onProgressUpdate: vi.fn(),
getCurrentStatus: vi.fn(),
dispose: vi.fn(),
setSystemState: vi.fn(),
})),
}))
// Mock telemetry
vi.mock("@roo-code/telemetry", () => ({
TelemetryService: {
instance: {
captureEvent: vi.fn(),
},
},
}))
// Mock service factory
vi.mock("../service-factory")
const MockedCodeIndexServiceFactory = CodeIndexServiceFactory as MockedClass<typeof CodeIndexServiceFactory>
describe("CodeIndexManager - Ignore Integration Tests", () => {
let mockContext: any
let manager: CodeIndexManager
beforeEach(() => {
// Clear all instances before each test
CodeIndexManager.disposeAll()
mockContext = {
subscriptions: [],
workspaceState: {} as any,
globalState: {} as any,
extensionUri: {} as any,
extensionPath: "/test/extension",
asAbsolutePath: vi.fn(),
storageUri: {} as any,
storagePath: "/test/storage",
globalStorageUri: {} as any,
globalStoragePath: "/test/global-storage",
logUri: {} as any,
logPath: "/test/log",
extensionMode: 3, // vscode.ExtensionMode.Test
secrets: {} as any,
environmentVariableCollection: {} as any,
extension: {} as any,
languageModelAccessInformation: {} as any,
}
manager = CodeIndexManager.getInstance(mockContext)!
})
afterEach(() => {
CodeIndexManager.disposeAll()
vi.clearAllMocks()
})
describe("gitignore integration", () => {
it("should load and apply .gitignore patterns during service recreation", async () => {
// Mock .gitignore file discovery and content
const { findGitignoreFiles } = await import("../../glob/list-files")
const mockFindGitignoreFiles = findGitignoreFiles as any
mockFindGitignoreFiles.mockResolvedValue(["/test/workspace/.gitignore"])
// Mock .gitignore content
mockFs.readFile.mockResolvedValue("node_modules/\n*.log\n.env")
// Mock config manager
const mockConfigManager = {
loadConfiguration: vi.fn().mockResolvedValue({ requiresRestart: false }),
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vi.fn().mockReturnValue({
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
openAiOptions: { openAiNativeApiKey: "test-key" },
qdrantUrl: "http://localhost:6333",
qdrantApiKey: "test-key",
searchMinScore: 0.4,
}),
}
;(manager as any)._configManager = mockConfigManager
// Mock cache manager
const mockCacheManager = {
initialize: vi.fn(),
clearCacheFile: vi.fn(),
}
;(manager as any)._cacheManager = mockCacheManager
// Mock service factory
const mockServiceFactoryInstance = {
createServices: vi.fn().mockReturnValue({
embedder: { embedderInfo: { name: "openai" } },
vectorStore: {},
scanner: {},
fileWatcher: {
onDidStartBatchProcessing: vi.fn(),
onBatchProgressUpdate: vi.fn(),
watch: vi.fn(),
stopWatcher: vi.fn(),
dispose: vi.fn(),
},
}),
validateEmbedder: vi.fn().mockResolvedValue({ valid: true }),
}
MockedCodeIndexServiceFactory.mockImplementation(() => mockServiceFactoryInstance as any)
// Act - call _recreateServices which should load .gitignore
await (manager as any)._recreateServices()
// Assert
expect(mockFindGitignoreFiles).toHaveBeenCalledWith("/test/workspace")
expect(mockFs.readFile).toHaveBeenCalledWith("/test/workspace/.gitignore", "utf8")
expect(mockServiceFactoryInstance.createServices).toHaveBeenCalled()
// Verify that the ignore instance was passed to createServices with .gitignore patterns
const createServicesCall = mockServiceFactoryInstance.createServices.mock.calls[0]
const ignoreInstance = createServicesCall[2] // Third parameter is the ignore instance
// Test that the ignore instance has the expected patterns
expect(ignoreInstance.ignores("node_modules/package.json")).toBe(true)
expect(ignoreInstance.ignores("debug.log")).toBe(true)
expect(ignoreInstance.ignores(".env")).toBe(true)
expect(ignoreInstance.ignores(".gitignore")).toBe(true) // Should always ignore .gitignore files
expect(ignoreInstance.ignores("src/main.ts")).toBe(false)
})
it("should handle missing .gitignore files gracefully", async () => {
// Mock no .gitignore files found
const { findGitignoreFiles } = await import("../../glob/list-files")
const mockFindGitignoreFiles = findGitignoreFiles as any
mockFindGitignoreFiles.mockResolvedValue([])
// Mock config manager
const mockConfigManager = {
loadConfiguration: vi.fn().mockResolvedValue({ requiresRestart: false }),
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vi.fn().mockReturnValue({
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
openAiOptions: { openAiNativeApiKey: "test-key" },
qdrantUrl: "http://localhost:6333",
qdrantApiKey: "test-key",
searchMinScore: 0.4,
}),
}
;(manager as any)._configManager = mockConfigManager
// Mock cache manager
const mockCacheManager = {
initialize: vi.fn(),
clearCacheFile: vi.fn(),
}
;(manager as any)._cacheManager = mockCacheManager
// Mock service factory
const mockServiceFactoryInstance = {
createServices: vi.fn().mockReturnValue({
embedder: { embedderInfo: { name: "openai" } },
vectorStore: {},
scanner: {},
fileWatcher: {
onDidStartBatchProcessing: vi.fn(),
onBatchProgressUpdate: vi.fn(),
watch: vi.fn(),
stopWatcher: vi.fn(),
dispose: vi.fn(),
},
}),
validateEmbedder: vi.fn().mockResolvedValue({ valid: true }),
}
MockedCodeIndexServiceFactory.mockImplementation(() => mockServiceFactoryInstance as any)
// Act - should not throw even with no .gitignore files
await expect((manager as any)._recreateServices()).resolves.not.toThrow()
// Assert
expect(mockFindGitignoreFiles).toHaveBeenCalledWith("/test/workspace")
expect(mockFs.readFile).not.toHaveBeenCalled()
expect(mockServiceFactoryInstance.createServices).toHaveBeenCalled()
// Verify that an ignore instance was still created (even if empty)
const createServicesCall = mockServiceFactoryInstance.createServices.mock.calls[0]
const ignoreInstance = createServicesCall[2]
// Should still ignore .gitignore files themselves
expect(ignoreInstance.ignores(".gitignore")).toBe(true)
expect(ignoreInstance.ignores("src/main.ts")).toBe(false)
})
})
describe("rooignore integration", () => {
it("should preserve RooIgnoreController instance across service recreations", async () => {
// Mock file existence check
const { fileExistsAtPath } = await import("../../../utils/fs")
const mockFileExistsAtPath = fileExistsAtPath as any
mockFileExistsAtPath.mockResolvedValue(true)
// Mock .rooignore content
mockFs.readFile.mockResolvedValue("*.secret\ntemp/")
// Mock config manager
const mockConfigManager = {
loadConfiguration: vi.fn().mockResolvedValue({ requiresRestart: false }),
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vi.fn().mockReturnValue({
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
openAiOptions: { openAiNativeApiKey: "test-key" },
qdrantUrl: "http://localhost:6333",
qdrantApiKey: "test-key",
searchMinScore: 0.4,
}),
}
;(manager as any)._configManager = mockConfigManager
// Mock cache manager
const mockCacheManager = {
initialize: vi.fn(),
clearCacheFile: vi.fn(),
}
;(manager as any)._cacheManager = mockCacheManager
// Mock .gitignore discovery
const { findGitignoreFiles } = await import("../../glob/list-files")
const mockFindGitignoreFiles = findGitignoreFiles as any
mockFindGitignoreFiles.mockResolvedValue([])
// Mock service factory
const mockServiceFactoryInstance = {
createServices: vi.fn().mockReturnValue({
embedder: { embedderInfo: { name: "openai" } },
vectorStore: {},
scanner: {},
fileWatcher: {
onDidStartBatchProcessing: vi.fn(),
onBatchProgressUpdate: vi.fn(),
watch: vi.fn(),
stopWatcher: vi.fn(),
dispose: vi.fn(),
},
}),
validateEmbedder: vi.fn().mockResolvedValue({ valid: true }),
}
MockedCodeIndexServiceFactory.mockImplementation(() => mockServiceFactoryInstance as any)
// Act - call _recreateServices twice to simulate "Clear Index Data" scenario
await (manager as any)._recreateServices()
const firstRooIgnoreController = (manager as any)._rooIgnoreController
await (manager as any)._recreateServices()
const secondRooIgnoreController = (manager as any)._rooIgnoreController
// Assert - should be the same instance (preserved across recreations)
expect(firstRooIgnoreController).toBe(secondRooIgnoreController)
expect(firstRooIgnoreController).toBeDefined()
// Verify that loadRooIgnore was called on both recreations
expect(mockFileExistsAtPath).toHaveBeenCalledWith("/test/workspace/.rooignore")
expect(mockFs.readFile).toHaveBeenCalledWith("/test/workspace/.rooignore", "utf8")
// Verify that the RooIgnoreController was passed to createServices
expect(mockServiceFactoryInstance.createServices).toHaveBeenCalledTimes(2)
const firstCall = mockServiceFactoryInstance.createServices.mock.calls[0]
const secondCall = mockServiceFactoryInstance.createServices.mock.calls[1]
// Fourth parameter should be the RooIgnoreController
expect(firstCall[3]).toBe(firstRooIgnoreController)
expect(secondCall[3]).toBe(secondRooIgnoreController)
expect(firstCall[3]).toBe(secondCall[3]) // Same instance
})
it("should reload .rooignore patterns on each service recreation", async () => {
// Mock file existence check
const { fileExistsAtPath } = await import("../../../utils/fs")
const mockFileExistsAtPath = fileExistsAtPath as any
mockFileExistsAtPath.mockResolvedValue(true)
// Mock .rooignore content
mockFs.readFile.mockResolvedValue("*.secret\ntemp/")
// Create a spy on the RooIgnoreController's loadRooIgnore method
const mockLoadRooIgnore = vi.fn().mockResolvedValue(undefined)
// Mock config manager
const mockConfigManager = {
loadConfiguration: vi.fn().mockResolvedValue({ requiresRestart: false }),
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vi.fn().mockReturnValue({
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
openAiOptions: { openAiNativeApiKey: "test-key" },
qdrantUrl: "http://localhost:6333",
qdrantApiKey: "test-key",
searchMinScore: 0.4,
}),
}
;(manager as any)._configManager = mockConfigManager
// Mock cache manager
const mockCacheManager = {
initialize: vi.fn(),
clearCacheFile: vi.fn(),
}
;(manager as any)._cacheManager = mockCacheManager
// Mock .gitignore discovery
const { findGitignoreFiles } = await import("../../glob/list-files")
const mockFindGitignoreFiles = findGitignoreFiles as any
mockFindGitignoreFiles.mockResolvedValue([])
// Pre-set a mock RooIgnoreController to test reloading
;(manager as any)._rooIgnoreController = {
loadRooIgnore: mockLoadRooIgnore,
dispose: vi.fn(),
}
// Mock service factory
const mockServiceFactoryInstance = {
createServices: vi.fn().mockReturnValue({
embedder: { embedderInfo: { name: "openai" } },
vectorStore: {},
scanner: {},
fileWatcher: {
onDidStartBatchProcessing: vi.fn(),
onBatchProgressUpdate: vi.fn(),
watch: vi.fn(),
stopWatcher: vi.fn(),
dispose: vi.fn(),
},
}),
validateEmbedder: vi.fn().mockResolvedValue({ valid: true }),
}
MockedCodeIndexServiceFactory.mockImplementation(() => mockServiceFactoryInstance as any)
// Act - call _recreateServices
await (manager as any)._recreateServices()
// Assert - loadRooIgnore should have been called to reload patterns
expect(mockLoadRooIgnore).toHaveBeenCalledTimes(1)
})
})
describe("integration with service factory", () => {
it("should pass both gitignore and rooignore controllers to service factory", async () => {
// Mock .gitignore discovery
const { findGitignoreFiles } = await import("../../glob/list-files")
const mockFindGitignoreFiles = findGitignoreFiles as any
mockFindGitignoreFiles.mockResolvedValue(["/test/workspace/.gitignore"])
// Mock .gitignore content
mockFs.readFile.mockImplementation((filePath: string) => {
if (filePath === "/test/workspace/.gitignore") {
return Promise.resolve("node_modules/\n*.log")
}
if (filePath === "/test/workspace/.rooignore") {
return Promise.resolve("*.secret\ntemp/")
}
return Promise.reject(new Error("File not found"))
})
// Mock file existence for .rooignore
const { fileExistsAtPath } = await import("../../../utils/fs")
const mockFileExistsAtPath = fileExistsAtPath as any
mockFileExistsAtPath.mockResolvedValue(true)
// Mock config manager
const mockConfigManager = {
loadConfiguration: vi.fn().mockResolvedValue({ requiresRestart: false }),
isFeatureConfigured: true,
isFeatureEnabled: true,
getConfig: vi.fn().mockReturnValue({
isConfigured: true,
embedderProvider: "openai",
modelId: "text-embedding-3-small",
openAiOptions: { openAiNativeApiKey: "test-key" },
qdrantUrl: "http://localhost:6333",
qdrantApiKey: "test-key",
searchMinScore: 0.4,
}),
}
;(manager as any)._configManager = mockConfigManager
// Mock cache manager
const mockCacheManager = {
initialize: vi.fn(),
clearCacheFile: vi.fn(),
}
;(manager as any)._cacheManager = mockCacheManager
// Mock service factory
const mockServiceFactoryInstance = {
createServices: vi.fn().mockReturnValue({
embedder: { embedderInfo: { name: "openai" } },
vectorStore: {},
scanner: {},
fileWatcher: {
onDidStartBatchProcessing: vi.fn(),
onBatchProgressUpdate: vi.fn(),
watch: vi.fn(),
stopWatcher: vi.fn(),
dispose: vi.fn(),
},
}),
validateEmbedder: vi.fn().mockResolvedValue({ valid: true }),
}
MockedCodeIndexServiceFactory.mockImplementation(() => mockServiceFactoryInstance as any)
// Act
await (manager as any)._recreateServices()
// Assert
expect(mockServiceFactoryInstance.createServices).toHaveBeenCalledTimes(1)
const createServicesCall = mockServiceFactoryInstance.createServices.mock.calls[0]
// Verify parameters: context, cacheManager, ignoreInstance, rooIgnoreController
expect(createServicesCall).toHaveLength(4)
expect(createServicesCall[0]).toBe(mockContext) // context
expect(createServicesCall[1]).toBe(mockCacheManager) // cacheManager
// Third parameter should be ignore instance with .gitignore patterns
const ignoreInstance = createServicesCall[2]
expect(ignoreInstance.ignores("node_modules/package.json")).toBe(true)
expect(ignoreInstance.ignores("debug.log")).toBe(true)
expect(ignoreInstance.ignores(".gitignore")).toBe(true)
// Fourth parameter should be RooIgnoreController
const rooIgnoreController = createServicesCall[3]
expect(rooIgnoreController).toBeDefined()
expect(rooIgnoreController).toBe((manager as any)._rooIgnoreController)
})
})
})

View file

@ -12,7 +12,17 @@ vi.mock("vscode", () => ({
index: 0,
},
],
createFileSystemWatcher: vi.fn(() => ({
onDidCreate: vi.fn(),
onDidChange: vi.fn(),
onDidDelete: vi.fn(),
dispose: vi.fn(),
})),
},
RelativePattern: vi.fn().mockImplementation((base, pattern) => ({
base,
pattern,
})),
}))
// Mock only the essential dependencies
@ -178,6 +188,10 @@ describe("CodeIndexManager - handleSettingsChange regression", () => {
// Simulate an initialized manager by setting the required properties
;(manager as any)._orchestrator = { stopWatcher: vi.fn() }
;(manager as any)._searchService = {}
;(manager as any)._rooIgnoreController = {
dispose: vi.fn(),
loadRooIgnore: vi.fn().mockResolvedValue(undefined),
}
// Verify manager is considered initialized
expect(manager.isInitialized).toBe(true)

View file

@ -12,9 +12,11 @@ import { CacheManager } from "./cache-manager"
import fs from "fs/promises"
import ignore from "ignore"
import path from "path"
import { findGitignoreFiles } from "../glob/list-files"
import { t } from "../../i18n"
import { TelemetryService } from "@roo-code/telemetry"
import { TelemetryEventName } from "@roo-code/types"
import { RooIgnoreController } from "../../core/ignore/RooIgnoreController"
export class CodeIndexManager {
// --- Singleton Implementation ---
@ -27,6 +29,7 @@ export class CodeIndexManager {
private _orchestrator: CodeIndexOrchestrator | undefined
private _searchService: CodeIndexSearchService | undefined
private _cacheManager: CacheManager | undefined
private _rooIgnoreController: RooIgnoreController | undefined
public static getInstance(context: vscode.ExtensionContext): CodeIndexManager | undefined {
// Use first workspace folder consistently
@ -70,7 +73,13 @@ export class CodeIndexManager {
}
private assertInitialized() {
if (!this._configManager || !this._orchestrator || !this._searchService || !this._cacheManager) {
if (
!this._configManager ||
!this._orchestrator ||
!this._searchService ||
!this._cacheManager ||
!this._rooIgnoreController
) {
throw new Error("CodeIndexManager not initialized. Call initialize() first.")
}
}
@ -100,6 +109,13 @@ export class CodeIndexManager {
}
}
/**
* Get the global RooIgnoreController instance
*/
public get rooIgnoreController(): RooIgnoreController | undefined {
return this._rooIgnoreController
}
/**
* Initializes the manager with configuration and dependent services.
* Must be called before using any other methods.
@ -186,6 +202,9 @@ export class CodeIndexManager {
if (this._orchestrator) {
this.stopWatcher()
}
if (this._rooIgnoreController) {
this._rooIgnoreController.dispose()
}
this._stateManager.dispose()
}
@ -228,6 +247,7 @@ export class CodeIndexManager {
// Clear existing services to ensure clean state
this._orchestrator = undefined
this._searchService = undefined
// Note: Keep _rooIgnoreController to preserve file watchers unless it doesn't exist
// (Re)Initialize service factory
this._serviceFactory = new CodeIndexServiceFactory(
@ -244,26 +264,41 @@ export class CodeIndexManager {
return
}
const ignorePath = path.join(workspacePath, ".gitignore")
// Load all .gitignore files from workspace root up to parent directories
try {
const content = await fs.readFile(ignorePath, "utf8")
ignoreInstance.add(content)
const gitignoreFiles = await findGitignoreFiles(workspacePath)
for (const gitignoreFile of gitignoreFiles) {
try {
const content = await fs.readFile(gitignoreFile, "utf8")
ignoreInstance.add(content)
} catch (error) {
console.warn(`Failed to read .gitignore file at ${gitignoreFile}:`, error)
}
}
// Always ignore .gitignore files themselves
ignoreInstance.add(".gitignore")
} catch (error) {
// Should never happen: reading file failed even though it exists
console.error("Unexpected error loading .gitignore:", error)
console.error("Error finding .gitignore files:", error)
TelemetryService.instance.captureEvent(TelemetryEventName.CODE_INDEX_ERROR, {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined,
location: "_recreateServices",
location: "_recreateServices.gitignore",
})
}
// Initialize or reuse RooIgnoreController with file watchers
if (!this._rooIgnoreController) {
this._rooIgnoreController = new RooIgnoreController(workspacePath)
}
// Always reload .rooignore patterns to ensure they're up to date
await this._rooIgnoreController.loadRooIgnore()
// (Re)Create shared service instances
const { embedder, vectorStore, scanner, fileWatcher } = this._serviceFactory.createServices(
this.context,
this._cacheManager!,
ignoreInstance,
this._rooIgnoreController,
)
// Validate embedder configuration before proceeding

View file

@ -36,6 +36,7 @@ export class DirectoryScanner implements IDirectoryScanner {
private readonly codeParser: ICodeParser,
private readonly cacheManager: CacheManager,
private readonly ignoreInstance: Ignore,
private readonly rooIgnoreController?: RooIgnoreController,
) {}
/**
@ -62,10 +63,15 @@ export class DirectoryScanner implements IDirectoryScanner {
// Filter out directories (marked with trailing '/')
const filePaths = allPaths.filter((p) => !p.endsWith("/"))
// Initialize RooIgnoreController if not provided
const ignoreController = new RooIgnoreController(directoryPath)
await ignoreController.initialize()
// Use injected RooIgnoreController or create a fallback
let ignoreController: RooIgnoreController
if (this.rooIgnoreController) {
ignoreController = this.rooIgnoreController
} else {
// Fallback for backward compatibility
ignoreController = new RooIgnoreController(directoryPath)
await ignoreController.initialize()
}
// Filter paths using .rooignore
const allowedPaths = ignoreController.filterPaths(filePaths)

View file

@ -10,6 +10,7 @@ import { ICodeParser, IEmbedder, IFileWatcher, IVectorStore } from "./interfaces
import { CodeIndexConfigManager } from "./config-manager"
import { CacheManager } from "./cache-manager"
import { Ignore } from "ignore"
import { RooIgnoreController } from "../../core/ignore/RooIgnoreController"
import { t } from "../../i18n"
import { TelemetryService } from "@roo-code/telemetry"
import { TelemetryEventName } from "@roo-code/types"
@ -145,8 +146,16 @@ export class CodeIndexServiceFactory {
vectorStore: IVectorStore,
parser: ICodeParser,
ignoreInstance: Ignore,
rooIgnoreController?: RooIgnoreController,
): DirectoryScanner {
return new DirectoryScanner(embedder, vectorStore, parser, this.cacheManager, ignoreInstance)
return new DirectoryScanner(
embedder,
vectorStore,
parser,
this.cacheManager,
ignoreInstance,
rooIgnoreController,
)
}
/**
@ -158,8 +167,17 @@ export class CodeIndexServiceFactory {
vectorStore: IVectorStore,
cacheManager: CacheManager,
ignoreInstance: Ignore,
rooIgnoreController?: RooIgnoreController,
): IFileWatcher {
return new FileWatcher(this.workspacePath, context, cacheManager, embedder, vectorStore, ignoreInstance)
return new FileWatcher(
this.workspacePath,
context,
cacheManager,
embedder,
vectorStore,
ignoreInstance,
rooIgnoreController,
)
}
/**
@ -170,6 +188,7 @@ export class CodeIndexServiceFactory {
context: vscode.ExtensionContext,
cacheManager: CacheManager,
ignoreInstance: Ignore,
rooIgnoreController?: RooIgnoreController,
): {
embedder: IEmbedder
vectorStore: IVectorStore
@ -184,8 +203,15 @@ export class CodeIndexServiceFactory {
const embedder = this.createEmbedder()
const vectorStore = this.createVectorStore()
const parser = codeParser
const scanner = this.createDirectoryScanner(embedder, vectorStore, parser, ignoreInstance)
const fileWatcher = this.createFileWatcher(context, embedder, vectorStore, cacheManager, ignoreInstance)
const scanner = this.createDirectoryScanner(embedder, vectorStore, parser, ignoreInstance, rooIgnoreController)
const fileWatcher = this.createFileWatcher(
context,
embedder,
vectorStore,
cacheManager,
ignoreInstance,
rooIgnoreController,
)
return {
embedder,

View file

@ -184,7 +184,7 @@ async function createIgnoreInstance(dirPath: string): Promise<ReturnType<typeof
/**
* Find all .gitignore files from the given directory up to the workspace root
*/
async function findGitignoreFiles(startPath: string): Promise<string[]> {
export async function findGitignoreFiles(startPath: string): Promise<string[]> {
const gitignoreFiles: string[] = []
let currentPath = startPath
@ -312,7 +312,6 @@ function isDirectoryExplicitlyIgnored(dirName: string): boolean {
return false
}
/**
* Combine file and directory results and format them properly
*/