Skip to content

Commit fe4714c

Browse files
authored
[content mappers] Always use canonical source file paths for composite project root checks (microsoft#64407)
1 parent 13ab32d commit fe4714c

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

‎tsc/internal/compiler/contentmapper_test.go‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,69 @@ func TestContentMapperVirtualExtensionSetsImpliedNodeFormat(t *testing.T) {
9191
assert.Equal(t, program.GetSourceFileMetaData(file.Path()).ImpliedNodeFormat, core.ResolutionModeESM)
9292
}
9393

94+
func TestCompositeProjectContentMapperSupplementalRoots(t *testing.T) {
95+
t.Parallel()
96+
contentMapperHost := fakeContentMapperHost{transform: func(fileName string, content string) (contentmapper.Result, error) {
97+
return contentmapper.Result{
98+
Text: "export {};",
99+
VirtualExtension: ".ts",
100+
Mappings: spanmap.New(nil),
101+
Supplemental: []contentmapper.MappedResult{{
102+
Text: "export {};",
103+
VirtualExtension: ".mts",
104+
Mappings: spanmap.New(nil),
105+
}},
106+
}, nil
107+
}}
108+
options := func() *core.CompilerOptions {
109+
return &core.CompilerOptions{
110+
Composite: core.TSTrue,
111+
SkipLibCheck: core.TSTrue,
112+
Module: core.ModuleKindESNext,
113+
ModuleResolution: core.ModuleResolutionKindBundler,
114+
}
115+
}
116+
117+
t.Run("listed canonical root", func(t *testing.T) {
118+
t.Parallel()
119+
program := newContentMapperProgramWithOptions(
120+
t,
121+
contentMapperHost,
122+
map[string]string{"/src/Component.vue": "<template />"},
123+
[]string{"/src/Component.vue"},
124+
options(),
125+
)
126+
127+
programDiagnostics := collectContentMapperDiagnostics(program)
128+
hasUnlistedFileDiagnostic := slices.ContainsFunc(programDiagnostics, func(diagnostic *ast.Diagnostic) bool {
129+
return diagnostic.Code() == diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern.Code()
130+
})
131+
assert.Assert(t, !hasUnlistedFileDiagnostic, "supplemental output should be covered by its listed canonical root: %v", programDiagnostics)
132+
})
133+
134+
t.Run("imported canonical file", func(t *testing.T) {
135+
t.Parallel()
136+
program := newContentMapperProgramWithOptions(
137+
t,
138+
contentMapperHost,
139+
map[string]string{
140+
"/src/index.ts": `import "./Component.vue";`,
141+
"/src/Component.vue": "<template />",
142+
},
143+
[]string{"/src/index.ts"},
144+
options(),
145+
)
146+
147+
unlistedFileDiagnosticCount := 0
148+
for _, diagnostic := range collectContentMapperDiagnostics(program) {
149+
if diagnostic.Code() == diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern.Code() {
150+
unlistedFileDiagnosticCount++
151+
}
152+
}
153+
assert.Equal(t, unlistedFileDiagnosticCount, 2)
154+
})
155+
}
156+
94157
func collectContentMapperDiagnostics(program *compiler.Program) []*ast.Diagnostic {
95158
ctx := context.Background()
96159
return slices.Concat(

‎tsc/internal/compiler/program.go‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,11 @@ func (p *Program) verifyCompilerOptions() {
10741074
}
10751075

10761076
for _, file := range p.files {
1077-
if sourceFileMayBeEmitted(file, p, false, false) && !rootPaths.Has(file.Path()) {
1077+
rootPath := file.Path()
1078+
if canonical := file.CanonicalSourceFile(); canonical != nil {
1079+
rootPath = canonical.Path()
1080+
}
1081+
if sourceFileMayBeEmitted(file, p, false, false) && !rootPaths.Has(rootPath) {
10781082
p.includeProcessor.addProcessingDiagnostic(&processingDiagnostic{
10791083
kind: processingDiagnosticKindExplainingFileInclude,
10801084
data: &includeExplainingDiagnostic{

0 commit comments

Comments
 (0)