12
12
13
13
namespace Microsoft . ComponentDetection . Common . DependencyGraph ;
14
14
15
+ using System . Collections . ObjectModel ;
15
16
using Microsoft . Extensions . Logging ;
16
17
17
18
public class ComponentRecorder : IComponentRecorder
18
19
{
19
- private readonly ConcurrentBag < SingleFileComponentRecorder > singleFileRecorders = [ ] ;
20
+ private readonly ConcurrentDictionary < string , SingleFileComponentRecorder > singleFileRecorders = [ ] ;
20
21
21
22
private readonly bool enableManualTrackingOfExplicitReferences ;
22
23
@@ -30,7 +31,7 @@ public ComponentRecorder(ILogger logger = null, bool enableManualTrackingOfExpli
30
31
31
32
public TypedComponent GetComponent ( string componentId )
32
33
{
33
- return this . singleFileRecorders . Select ( x => x . GetComponent ( componentId ) ? . Component ) . FirstOrDefault ( x => x != null ) ;
34
+ return this . singleFileRecorders . Values . Select ( x => x . GetComponent ( componentId ) ? . Component ) . FirstOrDefault ( x => x != null ) ;
34
35
}
35
36
36
37
public IEnumerable < DetectedComponent > GetDetectedComponents ( )
@@ -41,25 +42,21 @@ public IEnumerable<DetectedComponent> GetDetectedComponents()
41
42
return [ ] ;
42
43
}
43
44
44
- detectedComponents = this . singleFileRecorders
45
- . Select ( singleFileRecorder => singleFileRecorder . GetDetectedComponents ( ) . Values )
46
- . SelectMany ( x => x )
45
+ detectedComponents = this . singleFileRecorders . Values
46
+ . SelectMany ( singleFileRecorder => singleFileRecorder . GetDetectedComponents ( ) . Values )
47
47
. GroupBy ( x => x . Component . Id )
48
48
. Select ( grouping =>
49
49
{
50
50
// We pick a winner here -- any stateful props could get lost at this point. Only stateful prop still outstanding is ContainerDetails.
51
51
var winningDetectedComponent = grouping . First ( ) ;
52
- foreach ( var component in grouping )
52
+ foreach ( var component in grouping . Skip ( 1 ) )
53
53
{
54
- foreach ( var containerDetailId in component . ContainerDetailIds )
55
- {
56
- winningDetectedComponent . ContainerDetailIds . Add ( containerDetailId ) ;
57
- }
54
+ winningDetectedComponent . ContainerDetailIds . UnionWith ( component . ContainerDetailIds ) ;
58
55
}
59
56
60
57
return winningDetectedComponent ;
61
58
} )
62
- . ToImmutableList ( ) ;
59
+ . ToArray ( ) ;
63
60
64
61
return detectedComponents ;
65
62
}
@@ -71,11 +68,10 @@ public IEnumerable<string> GetSkippedComponents()
71
68
return [ ] ;
72
69
}
73
70
74
- return this . singleFileRecorders
75
- . Select ( x => x . GetSkippedComponents ( ) . Keys )
76
- . SelectMany ( x => x )
71
+ return this . singleFileRecorders . Values
72
+ . SelectMany ( x => x . GetSkippedComponents ( ) . Keys )
77
73
. Distinct ( )
78
- . ToImmutableList ( ) ;
74
+ . ToArray ( ) ;
79
75
}
80
76
81
77
public ISingleFileComponentRecorder CreateSingleFileComponentRecorder ( string location )
@@ -85,25 +81,20 @@ public ISingleFileComponentRecorder CreateSingleFileComponentRecorder(string loc
85
81
throw new ArgumentNullException ( nameof ( location ) ) ;
86
82
}
87
83
88
- var matching = this . singleFileRecorders . FirstOrDefault ( x => x . ManifestFileLocation == location ) ;
89
- if ( matching == null )
90
- {
91
- matching = new SingleFileComponentRecorder ( location , this , this . enableManualTrackingOfExplicitReferences , this . logger ) ;
92
- this . singleFileRecorders . Add ( matching ) ;
93
- }
94
-
95
- return matching ;
84
+ return this . singleFileRecorders . GetOrAdd ( location , loc => new SingleFileComponentRecorder ( loc , this , this . enableManualTrackingOfExplicitReferences , this . logger ) ) ;
96
85
}
97
86
98
87
public IReadOnlyDictionary < string , IDependencyGraph > GetDependencyGraphsByLocation ( )
99
88
{
100
- return this . singleFileRecorders . Where ( x => x . DependencyGraph . HasComponents ( ) )
101
- . ToImmutableDictionary ( x => x . ManifestFileLocation , x => x . DependencyGraph as IDependencyGraph ) ;
89
+ return new ReadOnlyDictionary < string , IDependencyGraph > (
90
+ this . singleFileRecorders . Values
91
+ . Where ( x => x . DependencyGraph . HasComponents ( ) )
92
+ . ToDictionary ( x => x . ManifestFileLocation , x => x . DependencyGraph as IDependencyGraph ) ) ;
102
93
}
103
94
104
95
internal DependencyGraph GetDependencyGraphForLocation ( string location )
105
96
{
106
- return this . singleFileRecorders . Single ( x => x . ManifestFileLocation == location ) . DependencyGraph ;
97
+ return this . singleFileRecorders [ location ] . DependencyGraph ;
107
98
}
108
99
109
100
public sealed class SingleFileComponentRecorder : ISingleFileComponentRecorder
@@ -183,16 +174,15 @@ public void RegisterUsage(
183
174
#endif
184
175
185
176
var componentId = detectedComponent . Component . Id ;
186
- DetectedComponent storedComponent = null ;
187
- lock ( this . registerUsageLock )
188
- {
189
- storedComponent = this . detectedComponentsInternal . GetOrAdd ( componentId , detectedComponent ) ;
177
+ var storedComponent = this . detectedComponentsInternal . GetOrAdd ( componentId , detectedComponent ) ;
190
178
191
- if ( ! string . IsNullOrWhiteSpace ( targetFramework ) )
192
- {
193
- storedComponent . TargetFrameworks . Add ( targetFramework . Trim ( ) ) ;
194
- }
179
+ if ( ! string . IsNullOrWhiteSpace ( targetFramework ) )
180
+ {
181
+ storedComponent . TargetFrameworks . Add ( targetFramework . Trim ( ) ) ;
182
+ }
195
183
184
+ lock ( this . registerUsageLock )
185
+ {
196
186
this . AddComponentToGraph ( this . ManifestFileLocation , detectedComponent , isExplicitReferencedDependency , parentComponentId , isDevelopmentDependency , dependencyScope ) ;
197
187
}
198
188
}
0 commit comments