Handle ts_libraries with both moduleNames and moduleRoots. PiperOrigin-RevId: 233815780
diff --git a/ts_auto_deps/analyze/analyze.go b/ts_auto_deps/analyze/analyze.go index 0960b57..e7f2851 100644 --- a/ts_auto_deps/analyze/analyze.go +++ b/ts_auto_deps/analyze/analyze.go
@@ -371,6 +371,26 @@ var ambientModuleDeclRE = regexp.MustCompile("(?m)^\\s*declare\\s+module\\s+['\"]([^'\"]+)['\"]\\s+\\{") +// pathStartsWith checks if path starts with prefix, checking each path segment, +// so that @angular/core starts with @angular/core, but @angular/core-bananas +// does not +func pathStartsWith(path, prefix string) bool { + pathParts := strings.Split(path, string(os.PathSeparator)) + prefixParts := strings.Split(prefix, string(os.PathSeparator)) + + if len(prefixParts) > len(pathParts) { + return false + } + + for i, prefixPart := range prefixParts { + if prefixPart != pathParts[i] { + return false + } + } + + return true +} + // 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 @@ -389,11 +409,33 @@ if moduleName == "" { continue } + if !pathStartsWith(i.importPath, moduleName) { + continue + } + // fmt.Printf("checking if %s is provided by %s\n", i.importPath, moduleName) + // if module root is a file, remove the file extension, since it'll be added + // by possibleFilepaths below + moduleRoot := stripTSExtension(stringAttribute(r, "module_root")) + _, pkg, _ := edit.ParseLabel(r.GetName()) + + // resolve the import path against the module name and module root, ie if + // the import path is @foo/bar and there's a moduleName of @foo the resolved + // import path is location/of/foo/bar, or if there's also a moduleRoot of + // baz, the resolved import path is location/of/foo/baz/bar + // + // using strings.TrimPrefix for trimming the path is ok, since + // pathStartsWith already checked that moduleName is a proper prefix of + // i.importPath + resolvedImportPath := filepath.Join(pkg, moduleRoot, strings.TrimPrefix(i.importPath, moduleName)) + + // enumerate all the possible filepaths for the resolved import path, and + // compare against all the srcs + possibleImportPaths := possibleFilepaths(resolvedImportPath) for _, src := range listAttribute(r, "srcs") { - _, _, file := edit.ParseLabel(src) - moduleImportPath := moduleName + "/" + stripTSExtension(file) - if i.importPath == moduleImportPath || i.importPath == strings.TrimSuffix(moduleImportPath, "/index") { - return r.GetName(), nil + for _, mi := range possibleImportPaths { + if mi == labelToPath(src) { + return r.GetName(), nil + } } } } @@ -522,6 +564,7 @@ for _, dep := range target.deps() { if edit.LabelsEqual(dep, imp.knownTarget, "") { + // fmt.Printf("%s provides %s\n", dep, imp.importPath) usedDeps[dep] = true report.NecessaryDependency = append(report.NecessaryDependency, imp.knownTarget) continue handlingImports