Skip to content

Commit 72a13a9

Browse files
fix(typescript-estree): improve project service error message when file extension missing from extraFileExtensions (typescript-eslint#10076)
* improve project service error message when file extension missing from extraFileExtensions * sahred
1 parent 7ea2074 commit 72a13a9

File tree

5 files changed

+94
-17
lines changed

5 files changed

+94
-17
lines changed

packages/typescript-estree/src/create-program/createProjectProgramError.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
11
import path from 'node:path';
22

3-
import * as ts from 'typescript';
3+
import type * as ts from 'typescript';
44

55
import type { ParseSettings } from '../parseSettings';
66
import { describeFilePath } from './describeFilePath';
7-
8-
const DEFAULT_EXTRA_FILE_EXTENSIONS = new Set<string>([
9-
ts.Extension.Ts,
10-
ts.Extension.Tsx,
11-
ts.Extension.Js,
12-
ts.Extension.Jsx,
13-
ts.Extension.Mjs,
14-
ts.Extension.Mts,
15-
ts.Extension.Cjs,
16-
ts.Extension.Cts,
17-
]);
7+
import { DEFAULT_EXTRA_FILE_EXTENSIONS } from './shared';
188

199
export function createProjectProgramError(
2010
parseSettings: ParseSettings,

packages/typescript-estree/src/create-program/shared.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ const DEFAULT_COMPILER_OPTIONS: ts.CompilerOptions = {
3838
checkJs: true,
3939
};
4040

41+
const DEFAULT_EXTRA_FILE_EXTENSIONS = new Set<string>([
42+
ts.Extension.Ts,
43+
ts.Extension.Tsx,
44+
ts.Extension.Js,
45+
ts.Extension.Jsx,
46+
ts.Extension.Mjs,
47+
ts.Extension.Mts,
48+
ts.Extension.Cjs,
49+
ts.Extension.Cts,
50+
]);
51+
4152
function createDefaultCompilerOptionsFromExtra(
4253
parseSettings: ParseSettings,
4354
): ts.CompilerOptions {
@@ -139,4 +150,5 @@ export {
139150
ensureAbsolutePath,
140151
getCanonicalFileName,
141152
getAstFromProgram,
153+
DEFAULT_EXTRA_FILE_EXTENSIONS,
142154
};

packages/typescript-estree/src/useProgramFromProjectService.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
ASTAndNoProgram,
1414
ASTAndProgram,
1515
} from './create-program/shared';
16+
import { DEFAULT_EXTRA_FILE_EXTENSIONS } from './create-program/shared';
1617
import { DEFAULT_PROJECT_FILES_ERROR_EXPLANATION } from './create-program/validateDefaultProjectForFilesGlob';
1718
import type { MutableParseSettings } from './parseSettings';
1819

@@ -72,10 +73,32 @@ function openClientFileFromProjectService(
7273
`${parseSettings.filePath} was included by allowDefaultProject but also was found in the project service. Consider removing it from allowDefaultProject.`,
7374
);
7475
}
75-
} else if (!isDefaultProjectAllowed) {
76-
throw new Error(
77-
`${parseSettings.filePath} was not found by the project service. Consider either including it in the tsconfig.json or including it in allowDefaultProject.`,
78-
);
76+
} else {
77+
const wasNotFound = `${parseSettings.filePath} was not found by the project service`;
78+
79+
const fileExtension = path.extname(parseSettings.filePath);
80+
const extraFileExtensions = parseSettings.extraFileExtensions;
81+
if (
82+
!DEFAULT_EXTRA_FILE_EXTENSIONS.has(fileExtension) &&
83+
!extraFileExtensions.includes(fileExtension)
84+
) {
85+
const nonStandardExt = `${wasNotFound} because the extension for the file (\`${fileExtension}\`) is non-standard`;
86+
if (extraFileExtensions.length > 0) {
87+
throw new Error(
88+
`${nonStandardExt}. It should be added to your existing \`parserOptions.extraFileExtensions\`.`,
89+
);
90+
} else {
91+
throw new Error(
92+
`${nonStandardExt}. You should add \`parserOptions.extraFileExtensions\` to your config.`,
93+
);
94+
}
95+
}
96+
97+
if (!isDefaultProjectAllowed) {
98+
throw new Error(
99+
`${wasNotFound}. Consider either including it in the tsconfig.json or including it in allowDefaultProject.`,
100+
);
101+
}
79102
}
80103

81104
// No a configFileName indicates this file wasn't included in a TSConfig.

packages/typescript-estree/tests/lib/parse.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ describe('parseAndGenerateServices', () => {
642642
it('extension matching the file name but not a file on disk', () => {
643643
expect(
644644
testExtraFileExtensions('other/unknownFileType.unknown', [
645-
'unknown',
645+
'.unknown',
646646
]),
647647
).toThrow(
648648
/unknownFileType\.unknown was not found by the project service/,

packages/typescript-estree/tests/lib/useProgramFromProjectService.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,4 +575,56 @@ If you absolutely need more files included, set parserOptions.projectService.max
575575
extraFileExtensions: [],
576576
});
577577
});
578+
579+
it('throws an error when a nonstandard file extension is used', () => {
580+
const filePath = `path/PascalCaseDirectory/vue-component.vue`;
581+
const { service } = createMockProjectService();
582+
service.openClientFile.mockReturnValueOnce({}).mockReturnValueOnce({});
583+
584+
expect(() =>
585+
useProgramFromProjectService(
586+
createProjectServiceSettings({
587+
allowDefaultProject: [mockParseSettings.filePath],
588+
service,
589+
}),
590+
{
591+
...mockParseSettings,
592+
filePath,
593+
},
594+
true,
595+
new Set(),
596+
),
597+
).toThrow(
598+
`${filePath} was not found by the project service because the extension for the file (\`${path.extname(
599+
filePath,
600+
)}\`) is non-standard. You should add \`parserOptions.extraFileExtensions\` to your config.`,
601+
);
602+
});
603+
604+
it('throws an error when a nonstandard file extension is used but not included in extraFileExtensions', () => {
605+
const filePath = `path/PascalCaseDirectory/vue-component.vue`;
606+
607+
const { service } = createMockProjectService();
608+
service.openClientFile.mockReturnValueOnce({}).mockReturnValueOnce({});
609+
610+
expect(() =>
611+
useProgramFromProjectService(
612+
createProjectServiceSettings({
613+
allowDefaultProject: [],
614+
service,
615+
}),
616+
{
617+
...mockParseSettings,
618+
filePath,
619+
extraFileExtensions: ['.svelte'],
620+
},
621+
true,
622+
new Set(),
623+
),
624+
).toThrow(
625+
`${filePath} was not found by the project service because the extension for the file (\`${path.extname(
626+
filePath,
627+
)}\`) is non-standard. It should be added to your existing \`parserOptions.extraFileExtensions\`.`,
628+
);
629+
});
578630
});

0 commit comments

Comments
 (0)