Skip to content

Commit 22a0e54

Browse files
devversionalxhub
authored andcommitted
fix(compiler-cli): support relative imports to symbols outside rootDir (#60555)
By default, the compiler-cli uses the relative import strategy when there is no `rootDir` or `rootDirs`. This is expected as everything is assumed to be somehow reachable through relative imports. With `rootDirs` that allow for a "virtual file system"-like environment, the compiler is not necessarily able to always construct proper relative imports. The compiler includes the `LogicalProjectStrategy` for this reason. This strategy is able to respect `rootDirs` to construct relative paths when possible. This logic currently accidentally triggers when there is a `rootDir` set. This option is not to be confused with the virtual directory option called `rootDirs`. The compiler currently confuses this and accidentally enters this mode when there is just a `rootDir`— breaking in monorepos that imports can point outside the `rootDir` to e.g. other compilation unit's `.d.ts` (which is valid; just not `.ts` sources can live outside the root dir). This is necessary for our Bazel toolchain migration. PR Close #60555
1 parent 7ff4235 commit 22a0e54

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

packages/compiler-cli/src/ngtsc/core/src/compiler.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,10 +1300,7 @@ export class NgCompiler {
13001300
// namespace" and the logic of `LogicalProjectStrategy` is required to generate correct
13011301
// imports which may cross these multiple directories. Otherwise, plain relative imports are
13021302
// sufficient.
1303-
if (
1304-
this.options.rootDir !== undefined ||
1305-
(this.options.rootDirs !== undefined && this.options.rootDirs.length > 0)
1306-
) {
1303+
if (this.options.rootDirs !== undefined && this.options.rootDirs.length > 0) {
13071304
// rootDirs logic is in effect - use the `LogicalProjectStrategy` for in-project relative
13081305
// imports.
13091306
localImportStrategy = new LogicalProjectStrategy(

packages/compiler-cli/test/ngtsc/imports_spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,45 @@ runInEachFileSystem(() => {
133133
expect(diags[0].file!.fileName).toEqual(absoluteFrom('/app/comp.ts'));
134134
expect(getDiagnosticSourceCode(diags[0])).toEqual('MyComponent');
135135
});
136+
137+
it('should be possible to use a directive outside of `rootDir` when no `rootDirs` are set.', () => {
138+
env.write(
139+
'tsconfig.json',
140+
JSON.stringify(
141+
{
142+
extends: './tsconfig-base.json',
143+
compilerOptions: {rootDir: './app'},
144+
},
145+
null,
146+
2,
147+
),
148+
);
149+
env.write(
150+
'/app/module.ts',
151+
`
152+
import {NgModule} from '@angular/core';
153+
import {ExternalDir} from '../lib/dir';
154+
155+
@NgModule({
156+
imports: [ExternalDir],
157+
})
158+
export class MyModule {}
159+
`,
160+
);
161+
env.write(
162+
'/lib/dir.d.ts',
163+
`
164+
import {ɵɵDirectiveDeclaration} from '@angular/core';
165+
166+
export class ExternalDir {
167+
static ɵdir: ɵɵDirectiveDeclaration<ExternalDir, '[external]', never, never, never, never, never, true>;
168+
}
169+
`,
170+
);
171+
172+
const diags = env.driveDiagnostics();
173+
expect(diags.length).toBe(0);
174+
});
136175
});
137176
});
138177

0 commit comments

Comments
 (0)