Allow for ts strictdeps to look at multiple declaration sites of a symbol
PiperOrigin-RevId: 290365047
diff --git a/internal/tsc_wrapped/strict_deps.ts b/internal/tsc_wrapped/strict_deps.ts
index c2cb723..447fc3e 100644
--- a/internal/tsc_wrapped/strict_deps.ts
+++ b/internal/tsc_wrapped/strict_deps.ts
@@ -85,15 +85,24 @@
if (!sym || !sym.declarations || sym.declarations.length < 1) {
continue;
}
- // Module imports can only have one declaration location.
- const declFileName = sym.declarations[0].getSourceFile().fileName;
- if (allowedMap[stripExt(declFileName)]) continue;
- const importName = path.posix.relative(rootDir, declFileName);
+ const declFileNames =
+ sym.declarations.map(decl => decl.getSourceFile().fileName);
+ if (declFileNames.find(
+ declFileName => !!allowedMap[stripExt(declFileName)])) {
+ continue;
+ }
+ const importNames = declFileNames.map(
+ declFileName => path.posix.relative(rootDir, declFileName));
+
+ const extraDeclarationLocationsMessage = (importNames.length < 2) ?
+ '' :
+ `(It is also declared in ${importNames.slice(1).join(', ')}) `;
result.push({
file: sf,
start: modSpec.getStart(),
length: modSpec.getEnd() - modSpec.getStart(),
- messageText: `transitive dependency on ${importName} not allowed. ` +
+ messageText: `transitive dependency on ${importNames[0]} not allowed. ` +
+ extraDeclarationLocationsMessage +
`Please add the BUILD target to your rule's deps.`,
category: ts.DiagnosticCategory.Error,
// semantics are close enough, needs taze.
diff --git a/internal/tsc_wrapped/strict_deps_test.ts b/internal/tsc_wrapped/strict_deps_test.ts
index 807e86e..1e3ae47 100644
--- a/internal/tsc_wrapped/strict_deps_test.ts
+++ b/internal/tsc_wrapped/strict_deps_test.ts
@@ -132,4 +132,26 @@
expect(diags[0].messageText)
.toMatch(/dependency on blaze-bin\/p\/sd1.d.ts not allowed/);
});
+
+ it('allows multiple declarations of the same clutz-generated module', () => {
+ const p = createProgram({
+ '/src/blaze-bin/p/js1.d.ts': `declare module 'goog:thing' {}`,
+ '/src/blaze-bin/p/js2.d.ts': `declare module 'goog:thing' {}`,
+ '/src/blaze-bin/p/js3.d.ts': `declare module 'goog:thing' {}`,
+ // Import from the middle one, to be sure it doesn't pass just because the
+ // order so happens that we checked the declaration from the first one
+ '/src/p/my.ts': `import {} from 'goog:thing'; // taze: from //p:js2`,
+ });
+ const good = checkModuleDeps(
+ p.getSourceFile('/src/p/my.ts')!, p.getTypeChecker(),
+ ['/src/blaze-bin/p/js2.d.ts'], '/src');
+ expect(good.length).toBe(0);
+
+ const bad = checkModuleDeps(
+ p.getSourceFile('/src/p/my.ts')!, p.getTypeChecker(), [], '/src');
+ expect(bad.length).toBe(1);
+ expect(bad[0].messageText)
+ .toContain(
+ '(It is also declared in blaze-bin/p/js2.d.ts, blaze-bin/p/js3.d.ts)');
+ });
});