25
25
import com .google .common .collect .ImmutableList ;
26
26
import com .google .common .collect .ImmutableMap ;
27
27
import com .google .devtools .build .docgen .annot .DocumentMethods ;
28
+ import com .google .devtools .build .lib .bazel .bzlmod .ModuleFileGlobals .ModuleExtensionUsageBuilder .ModuleExtensionProxy ;
28
29
import com .google .devtools .build .lib .bazel .bzlmod .Version .ParseException ;
29
30
import com .google .devtools .build .lib .cmdline .RepositoryName ;
30
31
import java .util .ArrayList ;
@@ -63,7 +64,7 @@ public class ModuleFileGlobals {
63
64
private final boolean ignoreDevDeps ;
64
65
private final Module .Builder module ;
65
66
private final Map <String , ModuleKey > deps = new LinkedHashMap <>();
66
- private final List <ModuleExtensionProxy > extensionProxies = new ArrayList <>();
67
+ private final List <ModuleExtensionUsageBuilder > extensionUsageBuilders = new ArrayList <>();
67
68
private final Map <String , ModuleOverride > overrides = new HashMap <>();
68
69
private final Map <String , RepoNameUsage > repoNameUsages = new HashMap <>();
69
70
@@ -373,38 +374,37 @@ public void registerToolchains(Sequence<?> toolchainLabels) throws EvalException
373
374
},
374
375
useStarlarkThread = true )
375
376
public ModuleExtensionProxy useExtension (
376
- String extensionBzlFile , String extensionName , boolean devDependency , StarlarkThread thread )
377
- throws EvalException {
378
- ModuleExtensionProxy newProxy =
379
- new ModuleExtensionProxy ( extensionBzlFile , extensionName , thread .getCallerLocation ());
377
+ String extensionBzlFile , String extensionName , boolean devDependency , StarlarkThread thread ) {
378
+ ModuleExtensionUsageBuilder newUsageBuilder =
379
+ new ModuleExtensionUsageBuilder (
380
+ extensionBzlFile , extensionName , thread .getCallerLocation ());
380
381
381
382
if (ignoreDevDeps && devDependency ) {
382
383
// This is a no-op proxy.
383
- return newProxy ;
384
+ return newUsageBuilder . getProxy ( devDependency ) ;
384
385
}
385
386
386
- // Find an existing proxy object corresponding to this extension.
387
- for (ModuleExtensionProxy proxy : extensionProxies ) {
388
- if (proxy .extensionBzlFile .equals (extensionBzlFile )
389
- && proxy .extensionName .equals (extensionName )) {
390
- return proxy ;
387
+ // Find an existing usage builder corresponding to this extension.
388
+ for (ModuleExtensionUsageBuilder usageBuilder : extensionUsageBuilders ) {
389
+ if (usageBuilder .extensionBzlFile .equals (extensionBzlFile )
390
+ && usageBuilder .extensionName .equals (extensionName )) {
391
+ return usageBuilder . getProxy ( devDependency ) ;
391
392
}
392
393
}
393
394
394
395
// If no such proxy exists, we can just use a new one.
395
- extensionProxies .add (newProxy );
396
- return newProxy ;
396
+ extensionUsageBuilders .add (newUsageBuilder );
397
+ return newUsageBuilder . getProxy ( devDependency ) ;
397
398
}
398
399
399
- @ StarlarkBuiltin (name = "module_extension_proxy" , documented = false )
400
- class ModuleExtensionProxy implements Structure {
400
+ class ModuleExtensionUsageBuilder {
401
401
private final String extensionBzlFile ;
402
402
private final String extensionName ;
403
403
private final Location location ;
404
404
private final HashBiMap <String , String > imports ;
405
405
private final ImmutableList .Builder <Tag > tags ;
406
406
407
- ModuleExtensionProxy (String extensionBzlFile , String extensionName , Location location ) {
407
+ ModuleExtensionUsageBuilder (String extensionBzlFile , String extensionName , Location location ) {
408
408
this .extensionBzlFile = extensionBzlFile ;
409
409
this .extensionName = extensionName ;
410
410
this .location = location ;
@@ -422,50 +422,69 @@ ModuleExtensionUsage buildUsage() {
422
422
.build ();
423
423
}
424
424
425
- void addImport (String localRepoName , String exportedName , Location location )
426
- throws EvalException {
427
- RepositoryName .validateUserProvidedRepoName (localRepoName );
428
- RepositoryName .validateUserProvidedRepoName (exportedName );
429
- addRepoNameUsage (localRepoName , "by a use_repo() call" , location );
430
- if (imports .containsValue (exportedName )) {
431
- String collisionRepoName = imports .inverse ().get (exportedName );
432
- throw Starlark .errorf (
433
- "The repo exported as '%s' by module extension '%s' is already imported at %s" ,
434
- exportedName , extensionName , repoNameUsages .get (collisionRepoName ).getWhere ());
435
- }
436
- imports .put (localRepoName , exportedName );
425
+ /**
426
+ * Creates a proxy with the specified dev_dependency bit that shares accumulated imports and
427
+ * tags with all other such proxies, thus preserving their order across dev/non-dev deps.
428
+ */
429
+ ModuleExtensionProxy getProxy (boolean devDependency ) {
430
+ return new ModuleExtensionProxy (devDependency );
437
431
}
438
432
439
- @ Nullable
440
- @ Override
441
- public Object getValue (String tagName ) throws EvalException {
442
- return new StarlarkValue () {
443
- @ StarlarkMethod (
444
- name = "call" ,
445
- selfCall = true ,
446
- documented = false ,
447
- extraKeywords = @ Param (name = "kwargs" ),
448
- useStarlarkThread = true )
449
- public void call (Dict <String , Object > kwargs , StarlarkThread thread ) {
450
- tags .add (
451
- Tag .builder ()
452
- .setTagName (tagName )
453
- .setAttributeValues (kwargs )
454
- .setLocation (thread .getCallerLocation ())
455
- .build ());
433
+ @ StarlarkBuiltin (name = "module_extension_proxy" , documented = false )
434
+ class ModuleExtensionProxy implements Structure {
435
+
436
+ private final boolean devDependency ;
437
+
438
+ private ModuleExtensionProxy (boolean devDependency ) {
439
+ this .devDependency = devDependency ;
440
+ }
441
+
442
+ void addImport (String localRepoName , String exportedName , Location location )
443
+ throws EvalException {
444
+ RepositoryName .validateUserProvidedRepoName (localRepoName );
445
+ RepositoryName .validateUserProvidedRepoName (exportedName );
446
+ addRepoNameUsage (localRepoName , "by a use_repo() call" , location );
447
+ if (imports .containsValue (exportedName )) {
448
+ String collisionRepoName = imports .inverse ().get (exportedName );
449
+ throw Starlark .errorf (
450
+ "The repo exported as '%s' by module extension '%s' is already imported at %s" ,
451
+ exportedName , extensionName , repoNameUsages .get (collisionRepoName ).getWhere ());
456
452
}
457
- } ;
458
- }
453
+ imports . put ( localRepoName , exportedName ) ;
454
+ }
459
455
460
- @ Override
461
- public ImmutableCollection <String > getFieldNames () {
462
- return ImmutableList .of ();
463
- }
456
+ @ Nullable
457
+ @ Override
458
+ public Object getValue (String tagName ) throws EvalException {
459
+ return new StarlarkValue () {
460
+ @ StarlarkMethod (
461
+ name = "call" ,
462
+ selfCall = true ,
463
+ documented = false ,
464
+ extraKeywords = @ Param (name = "kwargs" ),
465
+ useStarlarkThread = true )
466
+ public void call (Dict <String , Object > kwargs , StarlarkThread thread ) {
467
+ tags .add (
468
+ Tag .builder ()
469
+ .setTagName (tagName )
470
+ .setAttributeValues (kwargs )
471
+ .setDevDependency (devDependency )
472
+ .setLocation (thread .getCallerLocation ())
473
+ .build ());
474
+ }
475
+ };
476
+ }
464
477
465
- @ Nullable
466
- @ Override
467
- public String getErrorMessageForUnknownField (String field ) {
468
- return null ;
478
+ @ Override
479
+ public ImmutableCollection <String > getFieldNames () {
480
+ return ImmutableList .of ();
481
+ }
482
+
483
+ @ Nullable
484
+ @ Override
485
+ public String getErrorMessageForUnknownField (String field ) {
486
+ return null ;
487
+ }
469
488
}
470
489
}
471
490
@@ -821,8 +840,8 @@ public Module buildModule() {
821
840
.setDeps (ImmutableMap .copyOf (deps ))
822
841
.setOriginalDeps (ImmutableMap .copyOf (deps ))
823
842
.setExtensionUsages (
824
- extensionProxies .stream ()
825
- .map (ModuleExtensionProxy ::buildUsage )
843
+ extensionUsageBuilders .stream ()
844
+ .map (ModuleExtensionUsageBuilder ::buildUsage )
826
845
.collect (toImmutableList ()))
827
846
.build ();
828
847
}
0 commit comments