@@ -44,7 +44,7 @@ import { discoverEmbeddedRepoRoots } from './EmbeddedRepos';
4444import { IExtractor , ExtractorBase } from './ExtractorBase' ;
4545import { TypeScriptExtractor } from './extractors/TypeScript' ;
4646import { PythonExtractor } from './extractors/Python' ;
47- import { parseFile as parseFileWorker , loadGrammars as loadGrammarsWorker , destroy as destroyWorker } from './ParserWorker' ;
47+ import { parseFile as parseFileWorker , loadGrammars as loadGrammarsWorker , destroy as destroyWorker , recycleWorker as recycleWorkerFn , rejectAllPending as rejectAllPendingFn } from './ParserWorker' ;
4848
4949/** Параметры индексации. */
5050export interface IndexOptions {
@@ -391,6 +391,10 @@ export class ExtractionOrchestrator {
391391 const files = await scanDirectory ( this . rootDir , { onProgress, signal } ) ;
392392
393393 if ( signal ?. aborted ) {
394+ // Отменяем все ожидающие парсинги
395+ if ( PARSER_WORKER_AVAILABLE ) {
396+ rejectAllPendingFn ( ) ;
397+ }
394398 return this . abortResult ( startTime , filesIndexed , filesSkipped , filesErrored , totalNodes , totalEdges , errors ) ;
395399 }
396400
@@ -424,6 +428,12 @@ export class ExtractionOrchestrator {
424428
425429 // Обработка батчами для параллельного чтения файлов
426430 for ( let i = 0 ; i < files . length ; i += FILE_IO_BATCH_SIZE ) {
431+ // Отменяем все ожидающие парсинги при отмене
432+ if ( signal ?. aborted ) {
433+ if ( PARSER_WORKER_AVAILABLE ) {
434+ rejectAllPendingFn ( ) ;
435+ }
436+ }
427437 checkAbort ( signal ) ;
428438
429439 const batch = files . slice ( i , i + FILE_IO_BATCH_SIZE ) ;
@@ -497,7 +507,7 @@ export class ExtractionOrchestrator {
497507 continue ;
498508 }
499509
500- // Извлечение AST через экстрактор
510+ // Извлечение AST через экстрактор с 2-уровневым повтором
501511 let result : IExtractionResult ;
502512 try {
503513 if ( PARSER_WORKER_AVAILABLE ) {
@@ -506,15 +516,36 @@ export class ExtractionOrchestrator {
506516 result = this . extractFile ( filePath , content , language , frameworkNames ) ;
507517 }
508518 } catch ( parseErr ) {
509- processed ++ ;
510- filesErrored ++ ;
511- errors . push ( {
512- message : parseErr instanceof Error ? parseErr . message : String ( parseErr ) ,
513- filePath,
514- severity : 'error' ,
515- code : 'parse_error' ,
516- } ) ;
517- continue ;
519+ // Уровень 1: повтор с оригинальным содержимым
520+ try {
521+ if ( PARSER_WORKER_AVAILABLE ) {
522+ // Пересоздаём воркер перед повторной попыткой
523+ await recycleWorkerFn ( ) ;
524+ result = await parseFileWorker ( filePath , content , frameworkNames ?? [ ] , language , [ language ] ) ;
525+ } else {
526+ result = this . extractFile ( filePath , content , language , frameworkNames ) ;
527+ }
528+ } catch ( parseErr2 ) {
529+ // Уровень 2: удаление комментариев и повтор
530+ try {
531+ const stripped = this . stripComments ( content , language ) ;
532+ if ( PARSER_WORKER_AVAILABLE ) {
533+ result = await parseFileWorker ( filePath , stripped , frameworkNames ?? [ ] , language , [ language ] ) ;
534+ } else {
535+ result = this . extractFile ( filePath , stripped , language , frameworkNames ) ;
536+ }
537+ } catch ( parseErr3 ) {
538+ processed ++ ;
539+ filesErrored ++ ;
540+ errors . push ( {
541+ message : parseErr3 instanceof Error ? parseErr3 . message : String ( parseErr3 ) ,
542+ filePath,
543+ severity : 'error' ,
544+ code : 'parse_error' ,
545+ } ) ;
546+ continue ;
547+ }
548+ }
518549 }
519550
520551 processed ++ ;
@@ -1176,7 +1207,45 @@ await this.storeExtractionResult(fileRecord, result);
11761207 /**
11771208 * Извлекает AST из файла через соответствующий экстрактор.
11781209 */
1179- private extractFile (
1210+ private stripComments ( content : string , language : string ) : string {
1211+ const lines = content . split ( '\n' ) ;
1212+ if ( language === 'typescript' || language === 'cpp' || language === 'csharp' || language === 'java' ) {
1213+ const result : string [ ] = [ ] ;
1214+ let inBlock = false ;
1215+ for ( const line of lines ) {
1216+ let p = line ;
1217+ if ( inBlock ) {
1218+ const ei = p . indexOf ( '*/' ) ;
1219+ if ( ei !== - 1 ) { p = p . slice ( ei + 2 ) ; inBlock = false ; }
1220+ else { result . push ( '' ) ; continue ; }
1221+ }
1222+ const si = p . indexOf ( '//' ) ;
1223+ if ( si !== - 1 ) p = p . slice ( 0 , si ) ;
1224+ const bs = p . indexOf ( '/*' ) ;
1225+ if ( bs !== - 1 ) {
1226+ const be = p . indexOf ( '*/' , bs + 2 ) ;
1227+ if ( be !== - 1 ) p = p . slice ( 0 , bs ) + p . slice ( be + 2 ) ;
1228+ else { p = p . slice ( 0 , bs ) ; inBlock = true ; }
1229+ }
1230+ result . push ( p ) ;
1231+ }
1232+ return result . join ( '\n' ) ;
1233+ }
1234+ if ( language === 'python' || language === 'go' || language === 'rust' ) {
1235+ const result : string [ ] = [ ] ;
1236+ for ( const line of lines ) {
1237+ const t = line . trim ( ) ;
1238+ if ( t . startsWith ( '#' ) || t . startsWith ( '//' ) ) { result . push ( '' ) ; continue ; }
1239+ const ci = line . indexOf ( '#' ) ;
1240+ if ( ci !== - 1 ) result . push ( line . slice ( 0 , ci ) ) ;
1241+ else result . push ( line ) ;
1242+ }
1243+ return result . join ( '\n' ) ;
1244+ }
1245+ return content ;
1246+ }
1247+
1248+ private extractFile (
11801249 filePath : string ,
11811250 content : string ,
11821251 language : string ,
0 commit comments