@@ -73,14 +73,14 @@ type actionHandleKey source.Hash
73
73
// package (as different analyzers are applied, either in sequence or
74
74
// parallel), and across packages (as dependencies are analyzed).
75
75
type actionHandle struct {
76
+ key actionKey // just for String()
76
77
promise * memoize.Promise // [actionResult]
77
-
78
- analyzer * analysis.Analyzer
79
- pkg * pkg
80
78
}
81
79
82
80
// actionData is the successful result of analyzing a package.
83
81
type actionData struct {
82
+ analyzer * analysis.Analyzer
83
+ pkgTypes * types.Package // types only; don't keep syntax live
84
84
diagnostics []* source.Diagnostic
85
85
result interface {}
86
86
objectFacts map [objectFactKey ]analysis.Fact
@@ -168,9 +168,8 @@ func (s *snapshot) actionHandle(ctx context.Context, id PackageID, a *analysis.A
168
168
})
169
169
170
170
ah := & actionHandle {
171
- analyzer : a ,
172
- pkg : pkg ,
173
- promise : promise ,
171
+ key : key ,
172
+ promise : promise ,
174
173
}
175
174
176
175
s .mu .Lock ()
@@ -191,8 +190,12 @@ func buildActionKey(a *analysis.Analyzer, ph *packageHandle) actionHandleKey {
191
190
return actionHandleKey (source .Hashf ("%p%s" , a , ph .key [:]))
192
191
}
193
192
193
+ func (key actionKey ) String () string {
194
+ return fmt .Sprintf ("%s@%s" , key .analyzer , key .pkgid )
195
+ }
196
+
194
197
func (act * actionHandle ) String () string {
195
- return fmt . Sprintf ( "%s@%s" , act .analyzer , act . pkg . PkgPath () )
198
+ return act .key . String ( )
196
199
}
197
200
198
201
// actionImpl runs the analysis for action node (analyzer, pkg),
@@ -222,29 +225,20 @@ func actionImpl(ctx context.Context, snapshot *snapshot, deps []*actionHandle, a
222
225
223
226
mu .Lock ()
224
227
defer mu .Unlock ()
225
- if dep . pkg == pkg {
228
+ if data . pkgTypes == pkg . types {
226
229
// Same package, different analysis (horizontal edge):
227
230
// in-memory outputs of prerequisite analyzers
228
231
// become inputs to this analysis pass.
229
- inputs [dep .analyzer ] = data .result
232
+ inputs [data .analyzer ] = data .result
230
233
231
- } else if dep .analyzer == analyzer {
234
+ } else if data .analyzer == analyzer {
232
235
// Same analysis, different package (vertical edge):
233
236
// serialized facts produced by prerequisite analysis
234
237
// become available to this analysis pass.
235
238
for key , fact := range data .objectFacts {
236
- // Filter out facts related to objects
237
- // that are irrelevant downstream
238
- // (equivalently: not in the compiler export data).
239
- if ! exportedFrom (key .obj , dep .pkg .types ) {
240
- continue
241
- }
242
239
objectFacts [key ] = fact
243
240
}
244
241
for key , fact := range data .packageFacts {
245
- // TODO: filter out facts that belong to
246
- // packages not mentioned in the export data
247
- // to prevent side channels.
248
242
packageFacts [key ] = fact
249
243
}
250
244
@@ -268,7 +262,11 @@ func actionImpl(ctx context.Context, snapshot *snapshot, deps []*actionHandle, a
268
262
if source .IsCommandLineArguments (pkg .ID ()) {
269
263
errorf = fmt .Errorf // suppress reporting
270
264
}
271
- return errorf ("internal error: unexpected analysis dependency %s@%s -> %s" , analyzer .Name , pkg .ID (), dep )
265
+ err := errorf ("internal error: unexpected analysis dependency %s@%s -> %s" , analyzer .Name , pkg .ID (), dep )
266
+ // Log the event in any case, as the ultimate
267
+ // consumer of actionResult ignores errors.
268
+ event .Error (ctx , "analysis" , err )
269
+ return err
272
270
}
273
271
return nil
274
272
})
@@ -401,6 +399,16 @@ func actionImpl(ctx context.Context, snapshot *snapshot, deps []*actionHandle, a
401
399
panic (fmt .Sprintf ("%s:%s: Pass.ExportPackageFact(%T) called after Run" , analyzer .Name , pkg .PkgPath (), fact ))
402
400
}
403
401
402
+ // Filter out facts related to objects that are irrelevant downstream
403
+ // (equivalently: not in the compiler export data).
404
+ for key := range objectFacts {
405
+ if ! exportedFrom (key .obj , pkg .types ) {
406
+ delete (objectFacts , key )
407
+ }
408
+ }
409
+ // TODO: filter out facts that belong to packages not
410
+ // mentioned in the export data to prevent side channels.
411
+
404
412
var diagnostics []* source.Diagnostic
405
413
for _ , diag := range rawDiagnostics {
406
414
srcDiags , err := analysisDiagnosticDiagnostics (snapshot , pkg , analyzer , & diag )
@@ -411,6 +419,8 @@ func actionImpl(ctx context.Context, snapshot *snapshot, deps []*actionHandle, a
411
419
diagnostics = append (diagnostics , srcDiags ... )
412
420
}
413
421
return & actionData {
422
+ analyzer : analyzer ,
423
+ pkgTypes : pkg .types ,
414
424
diagnostics : diagnostics ,
415
425
result : result ,
416
426
objectFacts : objectFacts ,
@@ -434,8 +444,10 @@ func exportedFrom(obj types.Object, pkg *types.Package) bool {
434
444
case * types.Var :
435
445
return obj .Exported () && obj .Pkg () == pkg ||
436
446
obj .IsField ()
437
- case * types.TypeName , * types. Const :
447
+ case * types.TypeName :
438
448
return true
449
+ case * types.Const :
450
+ return obj .Exported () && obj .Pkg () == pkg
439
451
}
440
452
return false // Nil, Builtin, Label, or PkgName
441
453
}
0 commit comments