@@ -6,7 +6,7 @@ import { buildGraph } from '../../core/graph/buildGraph';
66import type { GraphRoot } from '../../core/graph/graphBuilder' ;
77import { getLayoutConfig , persistScanScope } from '../../core/workspace/config' ;
88import { scopeToLabel } from '../../core/workspace/scope' ;
9- import type { AnalysisResult , GraphData , ScanScope , ScannedFile , WebviewPayload } from '../../shared/types ' ;
9+ import type { AnalysisResult , GraphData , ScanScope , ScannedFile , WebviewPayload } from '../../shared/contracts ' ;
1010import type { RqvActivityViewProvider } from '../views/activityView' ;
1111import { GraphPanel } from '../views/graphPanel' ;
1212import { getWorkspaceFolders , scopeForWorkspace } from '../workspace/folders' ;
@@ -25,9 +25,36 @@ interface ScanAndPublishOptions {
2525}
2626
2727function mergeAnalysis ( results : AnalysisResult [ ] ) : AnalysisResult {
28+ const seenRecords = new Set < string > ( ) ;
2829 return results . reduce < AnalysisResult > (
2930 ( acc , current ) => {
30- acc . records . push ( ...current . records ) ;
31+ for ( const record of current . records ) {
32+ const dedupeKey = [
33+ record . file ,
34+ record . loc . line ,
35+ record . loc . column ,
36+ record . relation ,
37+ record . operation ,
38+ record . queryKey . id ,
39+ record . queryKey . display ,
40+ record . queryKey . matchMode ,
41+ record . queryKey . resolution ,
42+ record . queryKey . source ,
43+ record . resolution ,
44+ record . clientScopeId ?? '' ,
45+ record . executionScopeId ?? '' ,
46+ record . suiteScopeId ?? '' ,
47+ record . declaresDirectly === true ? '1' : '0' ,
48+ ] . join ( '|' ) ;
49+
50+ if ( seenRecords . has ( dedupeKey ) ) {
51+ continue ;
52+ }
53+
54+ seenRecords . add ( dedupeKey ) ;
55+ acc . records . push ( record ) ;
56+ }
57+
3158 acc . scannedFiles . push ( ...current . scannedFiles ) ;
3259 acc . parseErrors . push ( ...current . parseErrors ) ;
3360 acc . filesScanned += current . filesScanned ;
@@ -74,6 +101,7 @@ function buildScannedFiles(
74101) : ScannedFile [ ] {
75102 const multiRoot = targets . length > 1 ;
76103 const scannedFiles : ScannedFile [ ] = [ ] ;
104+ const seenPaths = new Set < string > ( ) ;
77105
78106 analyses . forEach ( ( analysis , index ) => {
79107 const target = targets [ index ] ;
@@ -83,6 +111,11 @@ function buildScannedFiles(
83111
84112 const workspaceName = target . workspace . name ;
85113 analysis . scannedFiles . forEach ( ( absolutePath ) => {
114+ if ( seenPaths . has ( absolutePath ) ) {
115+ return ;
116+ }
117+
118+ seenPaths . add ( absolutePath ) ;
86119 const relativePath = normalizeRelativePath ( target . workspace . uri . fsPath , absolutePath ) ;
87120 const depth = computeDepth ( relativePath ) ;
88121 scannedFiles . push ( {
@@ -151,7 +184,7 @@ export async function scanAndPublish({
151184 await persistScanScope ( scope ) ;
152185 }
153186
154- const panel = GraphPanel . createOrShow ( context . extensionUri ) ;
187+ const panel = GraphPanel . createOrShow ( context . extensionUri , getLayoutConfig ( ) ) ;
155188
156189 const result = await vscode . window . withProgress (
157190 {
0 commit comments