Check existing dependencies for ambient module declarations.
PiperOrigin-RevId: 233083308
diff --git a/ts_auto_deps/analyze/analyze.go b/ts_auto_deps/analyze/analyze.go
index 644110a..0960b57 100644
--- a/ts_auto_deps/analyze/analyze.go
+++ b/ts_auto_deps/analyze/analyze.go
@@ -7,6 +7,7 @@
"fmt"
"os"
"path/filepath"
+ "regexp"
"strings"
"github.com/bazelbuild/buildtools/edit"
@@ -327,7 +328,7 @@
continue handlingImports
}
}
- d, err := a.findRuleProvidingImport(target.dependencies, imp)
+ d, err := a.findExistingDepProvidingImport(ctx, target.dependencies, imp)
if err != nil {
return err
}
@@ -368,22 +369,27 @@
return paths
}
-// findRuleProvidingImport looks through a map of loaded rules for a rule
-// which can provide the passed import.
+var ambientModuleDeclRE = regexp.MustCompile("(?m)^\\s*declare\\s+module\\s+['\"]([^'\"]+)['\"]\\s+\\{")
+
+// findExistingDepProvidingImport looks through a map of the existing deps to
+// see if any of them provide the import in a way that can't be queried
+// for. E.g. if the build rule has a "module_name" attribute or if one
+// of the .d.ts sources has an ambient module declaration.
//
// If the import already has a knownTarget, findRuleProvidingImport will
// return the knownTarget.
-func (a *Analyzer) findRuleProvidingImport(rules map[string]*appb.Rule, i *ts_auto_depsImport) (string, error) {
+func (a *Analyzer) findExistingDepProvidingImport(ctx context.Context, rules map[string]*appb.Rule, i *ts_auto_depsImport) (string, error) {
if i.knownTarget != "" {
return i.knownTarget, nil
}
+
+ // check if any of the existing deps declare a module_name that matches the import
for _, r := range rules {
moduleName := stringAttribute(r, "module_name")
if moduleName == "" {
continue
}
- srcs := listAttribute(r, "srcs")
- for _, src := range srcs {
+ for _, src := range listAttribute(r, "srcs") {
_, _, file := edit.ParseLabel(src)
moduleImportPath := moduleName + "/" + stripTSExtension(file)
if i.importPath == moduleImportPath || i.importPath == strings.TrimSuffix(moduleImportPath, "/index") {
@@ -391,6 +397,41 @@
}
}
}
+
+ // check if any of the existing deps have .d.ts sources which have ambient module
+ // declarations
+ for _, r := range rules {
+ for _, src := range listAttribute(r, "srcs") {
+ filepath := labelToPath(src)
+ if !strings.HasSuffix(filepath, ".d.ts") {
+ continue
+ }
+
+ contents, err := platform.ReadFile(ctx, filepath)
+ if err != nil {
+ return "", fmt.Errorf("error reading file lookinf for ambient module decls: %s", err)
+ }
+
+ matches := ambientModuleDeclRE.FindAllStringSubmatch(string(contents), -1)
+
+ // put all the ambient modules into a set
+ declaredModules := make(map[string]bool)
+ for _, match := range matches {
+ declaredModules[match[1]] = true
+ }
+
+ // remove all the modules that were imported (ie all the modules that
+ // were being augmented/re-opened)
+ for _, mi := range parseImports(filepath, contents) {
+ delete(declaredModules, mi.importPath)
+ }
+
+ if declaredModules[i.importPath] {
+ debugf("found import %s in ambient module declaration in %s", i.importPath, r.GetName())
+ return r.GetName(), nil
+ }
+ }
+ }
return "", nil
}