mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-18 13:59:04 -05:00
Add error related to file not in rootDir and file not part of included root files at the references
This commit is contained in:
@@ -552,6 +552,12 @@ namespace ts {
|
||||
allDiagnostics?: Diagnostic[];
|
||||
}
|
||||
|
||||
interface RefFile extends TextRange {
|
||||
kind: RefFileKind;
|
||||
index: number;
|
||||
file: SourceFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if program structure is upto date or needs to be recreated
|
||||
*/
|
||||
@@ -717,6 +723,8 @@ namespace ts {
|
||||
let noDiagnosticsTypeChecker: TypeChecker;
|
||||
let classifiableNames: UnderscoreEscapedMap<true>;
|
||||
const ambientModuleNameToUnmodifiedFileName = createMap<string>();
|
||||
// Todo:: Use this to report why file was included in --extendedDiagnostics
|
||||
let refFileMap: MultiMap<ts.RefFile> | undefined;
|
||||
|
||||
const cachedSemanticDiagnosticsForFile: DiagnosticCache<Diagnostic> = {};
|
||||
const cachedDeclarationDiagnosticsForFile: DiagnosticCache<DiagnosticWithLocation> = {};
|
||||
@@ -913,6 +921,7 @@ namespace ts {
|
||||
getSourceFileByPath,
|
||||
getSourceFiles: () => files,
|
||||
getMissingFilePaths: () => missingFilePaths!, // TODO: GH#18217
|
||||
getRefFileMap: () => refFileMap,
|
||||
getCompilerOptions: () => options,
|
||||
getSyntacticDiagnostics,
|
||||
getOptionsDiagnostics,
|
||||
@@ -1391,6 +1400,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
missingFilePaths = oldProgram.getMissingFilePaths();
|
||||
refFileMap = oldProgram.getRefFileMap();
|
||||
|
||||
// update fileName -> file mapping
|
||||
for (const newSourceFile of newSourceFiles) {
|
||||
@@ -2179,25 +2189,24 @@ namespace ts {
|
||||
}
|
||||
|
||||
/** This has side effects through `findSourceFile`. */
|
||||
function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: PackageId | undefined, refFile?: SourceFile, refPos?: number, refEnd?: number): void {
|
||||
getSourceFileFromReferenceWorker(fileName,
|
||||
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, refFile!, refPos!, refEnd!, packageId), // TODO: GH#18217
|
||||
(diagnostic, ...args) => {
|
||||
fileProcessingDiagnostics.add(refFile !== undefined && refEnd !== undefined && refPos !== undefined
|
||||
? createFileDiagnostic(refFile, refPos, refEnd - refPos, diagnostic, ...args)
|
||||
: createCompilerDiagnostic(diagnostic, ...args));
|
||||
},
|
||||
refFile);
|
||||
function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: PackageId | undefined, refFile?: RefFile): void {
|
||||
getSourceFileFromReferenceWorker(
|
||||
fileName,
|
||||
fileName => findSourceFile(fileName, toPath(fileName), isDefaultLib, ignoreNoDefaultLib, refFile, packageId), // TODO: GH#18217
|
||||
(diagnostic, ...args) => fileProcessingDiagnostics.add(
|
||||
createRefFileDiagnostic(refFile, diagnostic, ...args)
|
||||
),
|
||||
refFile && refFile.file
|
||||
);
|
||||
}
|
||||
|
||||
function reportFileNamesDifferOnlyInCasingError(fileName: string, existingFileName: string, refFile: SourceFile, refPos: number, refEnd: number): void {
|
||||
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
|
||||
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
|
||||
Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName));
|
||||
}
|
||||
else {
|
||||
fileProcessingDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, fileName, existingFileName));
|
||||
}
|
||||
function reportFileNamesDifferOnlyInCasingError(fileName: string, existingFileName: string, refFile: RefFile | undefined): void {
|
||||
fileProcessingDiagnostics.add(createRefFileDiagnostic(
|
||||
refFile,
|
||||
Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing,
|
||||
fileName,
|
||||
existingFileName
|
||||
));
|
||||
}
|
||||
|
||||
function createRedirectSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string): SourceFile {
|
||||
@@ -2222,7 +2231,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Get source file from normalized fileName
|
||||
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
|
||||
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: RefFile | undefined, packageId: PackageId | undefined): SourceFile | undefined {
|
||||
const originalFileName = fileName;
|
||||
if (filesByName.has(path)) {
|
||||
const file = filesByName.get(path);
|
||||
@@ -2239,7 +2248,7 @@ namespace ts {
|
||||
const checkedAbsolutePath = getNormalizedAbsolutePathWithoutRoot(checkedName, currentDirectory);
|
||||
const inputAbsolutePath = getNormalizedAbsolutePathWithoutRoot(inputName, currentDirectory);
|
||||
if (checkedAbsolutePath !== inputAbsolutePath) {
|
||||
reportFileNamesDifferOnlyInCasingError(inputName, checkedName, refFile, refPos, refEnd);
|
||||
reportFileNamesDifferOnlyInCasingError(inputName, checkedName, refFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2266,6 +2275,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
addFileToRefFileMap(file || undefined, refFile);
|
||||
return file || undefined;
|
||||
}
|
||||
|
||||
@@ -2289,15 +2299,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
// We haven't looked for this file, do so now and cache result
|
||||
const file = host.getSourceFile(fileName, options.target!, hostErrorMessage => { // TODO: GH#18217
|
||||
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
|
||||
fileProcessingDiagnostics.add(createFileDiagnostic(refFile, refPos, refEnd - refPos,
|
||||
Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
}
|
||||
else {
|
||||
fileProcessingDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, hostErrorMessage));
|
||||
}
|
||||
}, shouldCreateNewSourceFile);
|
||||
const file = host.getSourceFile(
|
||||
fileName,
|
||||
options.target!,
|
||||
hostErrorMessage => fileProcessingDiagnostics.add(createRefFileDiagnostic(
|
||||
refFile,
|
||||
Diagnostics.Cannot_read_file_0_Colon_1,
|
||||
fileName,
|
||||
hostErrorMessage
|
||||
)),
|
||||
shouldCreateNewSourceFile
|
||||
);
|
||||
|
||||
if (packageId) {
|
||||
const packageIdKey = packageIdToString(packageId);
|
||||
@@ -2331,7 +2343,7 @@ namespace ts {
|
||||
// for case-sensitive file systems check if we've already seen some file with similar filename ignoring case
|
||||
const existingFile = filesByNameIgnoreCase!.get(pathLowerCase);
|
||||
if (existingFile) {
|
||||
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile, refPos, refEnd);
|
||||
reportFileNamesDifferOnlyInCasingError(fileName, existingFile.fileName, refFile);
|
||||
}
|
||||
else {
|
||||
filesByNameIgnoreCase!.set(pathLowerCase, file);
|
||||
@@ -2359,10 +2371,20 @@ namespace ts {
|
||||
processingOtherFiles!.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
addFileToRefFileMap(file, refFile);
|
||||
return file;
|
||||
}
|
||||
|
||||
function addFileToRefFileMap(file: SourceFile | undefined, refFile: RefFile | undefined) {
|
||||
if (refFile && file) {
|
||||
(refFileMap || (refFileMap = createMultiMap())).add(file.path, {
|
||||
kind: refFile.kind,
|
||||
index: refFile.index,
|
||||
file: refFile.file.path
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function addFileToFilesByName(file: SourceFile | undefined, path: Path, redirectedPath: Path | undefined) {
|
||||
if (redirectedPath) {
|
||||
filesByName.set(redirectedPath, file);
|
||||
@@ -2479,9 +2501,21 @@ namespace ts {
|
||||
}
|
||||
|
||||
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
|
||||
forEach(file.referencedFiles, ref => {
|
||||
forEach(file.referencedFiles, (ref, index) => {
|
||||
const referencedFileName = resolveTripleslashReference(ref.fileName, file.originalFileName);
|
||||
processSourceFile(referencedFileName, isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, file, ref.pos, ref.end);
|
||||
processSourceFile(
|
||||
referencedFileName,
|
||||
isDefaultLib,
|
||||
/*ignoreNoDefaultLib*/ false,
|
||||
/*packageId*/ undefined,
|
||||
{
|
||||
kind: RefFileKind.ReferenceFile,
|
||||
index,
|
||||
file,
|
||||
pos: ref.pos,
|
||||
end: ref.end
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2500,12 +2534,25 @@ namespace ts {
|
||||
// store resolved type directive on the file
|
||||
const fileName = ref.fileName.toLocaleLowerCase();
|
||||
setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective);
|
||||
processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end);
|
||||
processTypeReferenceDirective(
|
||||
fileName,
|
||||
resolvedTypeReferenceDirective,
|
||||
{
|
||||
kind: RefFileKind.TypeReferenceDirective,
|
||||
index: i,
|
||||
file,
|
||||
pos: ref.pos,
|
||||
end: ref.end
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function processTypeReferenceDirective(typeReferenceDirective: string, resolvedTypeReferenceDirective?: ResolvedTypeReferenceDirective,
|
||||
refFile?: SourceFile, refPos?: number, refEnd?: number): void {
|
||||
function processTypeReferenceDirective(
|
||||
typeReferenceDirective: string,
|
||||
resolvedTypeReferenceDirective?: ResolvedTypeReferenceDirective,
|
||||
refFile?: RefFile
|
||||
): void {
|
||||
|
||||
// If we already found this library as a primary reference - nothing to do
|
||||
const previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective);
|
||||
@@ -2518,7 +2565,7 @@ namespace ts {
|
||||
|
||||
if (resolvedTypeReferenceDirective.primary) {
|
||||
// resolved from the primary path
|
||||
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd); // TODO: GH#18217
|
||||
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile); // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
// If we already resolved to this file, it must have been a secondary reference. Check file contents
|
||||
@@ -2528,12 +2575,15 @@ namespace ts {
|
||||
if (resolvedTypeReferenceDirective.resolvedFileName !== previousResolution.resolvedFileName) {
|
||||
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName!);
|
||||
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName!)!.text) {
|
||||
fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, // TODO: GH#18217
|
||||
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
|
||||
typeReferenceDirective,
|
||||
resolvedTypeReferenceDirective.resolvedFileName,
|
||||
previousResolution.resolvedFileName
|
||||
));
|
||||
fileProcessingDiagnostics.add(
|
||||
createRefFileDiagnostic(
|
||||
refFile,
|
||||
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
|
||||
typeReferenceDirective,
|
||||
resolvedTypeReferenceDirective.resolvedFileName,
|
||||
previousResolution.resolvedFileName
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
// don't overwrite previous resolution result
|
||||
@@ -2541,14 +2591,18 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
// First resolution of this library
|
||||
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile, refPos, refEnd);
|
||||
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName!, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, resolvedTypeReferenceDirective.packageId, refFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth--;
|
||||
}
|
||||
else {
|
||||
fileProcessingDiagnostics.add(createDiagnostic(refFile!, refPos!, refEnd!, Diagnostics.Cannot_find_type_definition_file_for_0, typeReferenceDirective)); // TODO: GH#18217
|
||||
fileProcessingDiagnostics.add(createRefFileDiagnostic(
|
||||
refFile,
|
||||
Diagnostics.Cannot_find_type_definition_file_for_0,
|
||||
typeReferenceDirective
|
||||
));
|
||||
}
|
||||
|
||||
if (saveResolution) {
|
||||
@@ -2568,17 +2622,24 @@ namespace ts {
|
||||
const unqualifiedLibName = removeSuffix(removePrefix(libName, "lib."), ".d.ts");
|
||||
const suggestion = getSpellingSuggestion(unqualifiedLibName, libs, identity);
|
||||
const message = suggestion ? Diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1 : Diagnostics.Cannot_find_lib_definition_for_0;
|
||||
fileProcessingDiagnostics.add(createDiagnostic(file, libReference.pos, libReference.end, message, libName, suggestion));
|
||||
fileProcessingDiagnostics.add(createFileDiagnostic(
|
||||
file,
|
||||
libReference.pos,
|
||||
libReference.end - libReference.pos,
|
||||
message,
|
||||
libName,
|
||||
suggestion
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createDiagnostic(refFile: SourceFile, refPos: number, refEnd: number, message: DiagnosticMessage, ...args: any[]): Diagnostic {
|
||||
if (refFile === undefined || refPos === undefined || refEnd === undefined) {
|
||||
function createRefFileDiagnostic(refFile: RefFile | undefined, message: DiagnosticMessage, ...args: any[]): Diagnostic {
|
||||
if (!refFile) {
|
||||
return createCompilerDiagnostic(message, ...args);
|
||||
}
|
||||
else {
|
||||
return createFileDiagnostic(refFile, refPos, refEnd - refPos, message, ...args);
|
||||
return createFileDiagnostic(refFile.file, refFile.pos, refFile.end - refFile.pos, message, ...args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2632,7 +2693,20 @@ namespace ts {
|
||||
else if (shouldAddFile) {
|
||||
const path = toPath(resolvedFileName);
|
||||
const pos = skipTrivia(file.text, file.imports[i].pos);
|
||||
findSourceFile(resolvedFileName, path, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, file, pos, file.imports[i].end, resolution.packageId);
|
||||
findSourceFile(
|
||||
resolvedFileName,
|
||||
path,
|
||||
/*isDefaultLib*/ false,
|
||||
/*ignoreNoDefaultLib*/ false,
|
||||
{
|
||||
kind: RefFileKind.Import,
|
||||
index: i,
|
||||
file,
|
||||
pos,
|
||||
end: file.imports[i].end
|
||||
},
|
||||
resolution.packageId
|
||||
);
|
||||
}
|
||||
|
||||
if (isFromNodeModulesSearch) {
|
||||
@@ -2654,12 +2728,20 @@ namespace ts {
|
||||
function checkSourceFilesBelongToPath(sourceFiles: ReadonlyArray<SourceFile>, rootDirectory: string): boolean {
|
||||
let allFilesBelongToPath = true;
|
||||
const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory));
|
||||
let rootPaths: Map<true> | undefined;
|
||||
|
||||
for (const sourceFile of sourceFiles) {
|
||||
if (!sourceFile.isDeclarationFile) {
|
||||
const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory));
|
||||
if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, sourceFile.fileName, rootDirectory));
|
||||
if (!rootPaths) rootPaths = arrayToSet(rootNames, toPath);
|
||||
addProgramDiagnosticAtRefPath(
|
||||
sourceFile,
|
||||
rootPaths,
|
||||
Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files,
|
||||
sourceFile.fileName,
|
||||
rootDirectory
|
||||
);
|
||||
allFilesBelongToPath = false;
|
||||
}
|
||||
}
|
||||
@@ -2771,12 +2853,18 @@ namespace ts {
|
||||
|
||||
// List of collected files is complete; validate exhautiveness if this is a project with a file list
|
||||
if (options.composite) {
|
||||
const rootPaths = rootNames.map(toPath);
|
||||
const rootPaths = arrayToSet(rootNames, toPath);
|
||||
for (const file of files) {
|
||||
// Ignore file that is not emitted
|
||||
if (!sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect)) continue;
|
||||
if (rootPaths.indexOf(file.path) === -1) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern, file.fileName, options.configFilePath || ""));
|
||||
if (!rootPaths.has(file.path)) {
|
||||
addProgramDiagnosticAtRefPath(
|
||||
file,
|
||||
rootPaths,
|
||||
Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern,
|
||||
file.fileName,
|
||||
options.configFilePath || ""
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2984,6 +3072,35 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function addProgramDiagnosticAtRefPath(file: SourceFile, rootPaths: Map<true>, message: DiagnosticMessage, ...args: (string | number | undefined)[]) {
|
||||
const refPaths = refFileMap && refFileMap.get(file.path);
|
||||
const refPathToReportErrorOn = forEach(refPaths, refPath => rootPaths.has(refPath.file) ? refPath : undefined) ||
|
||||
elementAt(refPaths, 0);
|
||||
if (refPathToReportErrorOn) {
|
||||
const refFile = Debug.assertDefined(getSourceFileByPath(refPathToReportErrorOn.file));
|
||||
const { kind, index } = refPathToReportErrorOn;
|
||||
let pos: number, end: number;
|
||||
switch (kind) {
|
||||
case RefFileKind.Import:
|
||||
pos = skipTrivia(refFile.text, refFile.imports[index].pos);
|
||||
end = refFile.imports[index].end;
|
||||
break;
|
||||
case RefFileKind.ReferenceFile:
|
||||
({ pos, end } = refFile.referencedFiles[index]);
|
||||
break;
|
||||
case RefFileKind.TypeReferenceDirective:
|
||||
({ pos, end } = refFile.typeReferenceDirectives[index]);
|
||||
break;
|
||||
default:
|
||||
return Debug.assertNever(kind);
|
||||
}
|
||||
programDiagnostics.add(createFileDiagnostic(refFile, pos, end - pos, message, ...args));
|
||||
}
|
||||
else {
|
||||
programDiagnostics.add(createCompilerDiagnostic(message, ...args));
|
||||
}
|
||||
}
|
||||
|
||||
function verifyProjectReferences() {
|
||||
const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getOutputPathForBuildInfo(options) : undefined;
|
||||
forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => {
|
||||
|
||||
Reference in New Issue
Block a user