diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c24f570819e..c6cdceeb550 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2341,7 +2341,7 @@ namespace ts { function parseProjectReferenceConfigFile(ref: ProjectReference): { commandLine: ParsedCommandLine, sourceFile: SourceFile } | undefined { // The actual filename (i.e. add "/tsconfig.json" if necessary) - const refPath = resolveProjectReferencePath(host, ref); + const refPath = resolveProjectReferencePath(ref); // An absolute path pointing to the containing directory of the config file const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory()); const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile | undefined; @@ -2820,18 +2820,13 @@ namespace ts { }; } - export interface ResolveProjectReferencePathHost { - fileExists(fileName: string): boolean; - } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ - export function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName { - if (!host.fileExists(ref.path)) { - return combinePaths(ref.path, "tsconfig.json") as ResolvedConfigFileName; - } - return ref.path as ResolvedConfigFileName; + // TODO: Does this need to be exposed + export function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName { + return resolveConfigFileProjectName(ref.path); } /* @internal */ diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 599b6ddd882..54cd97644f6 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -598,7 +598,7 @@ namespace ts { function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { reportFileChangeDetected = true; - invalidateProject(resolved, reloadLevel); + invalidateResolvedProject(resolved, reloadLevel); scheduleBuildInvalidatedProject(); } @@ -716,7 +716,7 @@ namespace ts { if (project.projectReferences) { for (const ref of project.projectReferences) { usesPrepend = usesPrepend || !!(ref.prepend); - const resolvedRef = resolveProjectReferencePath(host, ref); + const resolvedRef = resolveProjectReferencePath(ref); const refStatus = getUpToDateStatus(parseConfigFile(resolvedRef)); // An upstream project is blocked @@ -795,16 +795,10 @@ namespace ts { } function invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel) { - const resolved = resolveProjectName(configFileName); - if (resolved === undefined) { - // If this was a rootName, we need to track it as missing. - // Otherwise we can just ignore it and have it possibly surface as an error in any downstream projects, - // if they exist - - // TODO: do those things - return; - } + invalidateResolvedProject(resolveProjectName(configFileName), reloadLevel); + } + function invalidateResolvedProject(resolved: ResolvedConfigFileName, reloadLevel?: ConfigFileProgramReloadLevel) { projectStatus.removeKey(resolved); if (options.watch) { diagnostics.removeKey(resolved); @@ -901,11 +895,9 @@ namespace ts { } } - function buildSingleInvalidatedProject(project: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { + function buildSingleInvalidatedProject(resolved: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { // TODO:: handle this in better way later - const resolved = resolveProjectName(project); - if (!resolved) return; // ?? const proj = parseConfigFile(resolved); if (!proj) return; // ? if (reloadLevel === ConfigFileProgramReloadLevel.Full) { @@ -915,7 +907,7 @@ namespace ts { } else if (reloadLevel === ConfigFileProgramReloadLevel.Partial) { // Update file names - const result = getFileNamesFromConfigSpecs(proj.configFileSpecs!, getDirectoryPath(project), proj.options, parseConfigFileHost); + const result = getFileNamesFromConfigSpecs(proj.configFileSpecs!, getDirectoryPath(resolved), proj.options, parseConfigFileHost); if (result.fileNames.length !== 0) { filterMutate(proj.errors, error => !isErrorNoInputFiles(error)); } @@ -927,14 +919,14 @@ namespace ts { } const status = getUpToDateStatus(proj); - verboseReportProjectStatus(project, status); + verboseReportProjectStatus(resolved, status); if (status.type === UpToDateStatusType.UpstreamBlocked) { if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); return; } - buildSingleProject(project); + buildSingleProject(resolved); } function createDependencyGraph(roots: ResolvedConfigFileName[]): DependencyGraph | undefined { @@ -982,10 +974,6 @@ namespace ts { if (parsed.projectReferences) { for (const ref of parsed.projectReferences) { const resolvedRefPath = resolveProjectName(ref.path); - if (resolvedRefPath === undefined) { - hadError = true; - break; - } visit(resolvedRefPath, inCircularContext || ref.circular); graph.addReference(projPath, resolvedRefPath); } @@ -1184,30 +1172,12 @@ namespace ts { return ExitStatus.Success; } - function resolveProjectName(name: string): ResolvedConfigFileName | undefined { - const fullPath = resolvePath(host.getCurrentDirectory(), name); - if (host.fileExists(fullPath)) { - return fullPath as ResolvedConfigFileName; - } - const fullPathWithTsconfig = combinePaths(fullPath, "tsconfig.json"); - if (host.fileExists(fullPathWithTsconfig)) { - return fullPathWithTsconfig as ResolvedConfigFileName; - } - // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better - host.reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_not_found, relName(fullPath))); - return undefined; + function resolveProjectName(name: string): ResolvedConfigFileName { + return resolveConfigFileProjectName(resolvePath(host.getCurrentDirectory(), name)); } function resolveProjectNames(configFileNames: ReadonlyArray): ResolvedConfigFileName[] | undefined { - const resolvedNames: ResolvedConfigFileName[] = []; - for (const name of configFileNames) { - const resolved = resolveProjectName(name); - if (resolved === undefined) { - return undefined; - } - resolvedNames.push(resolved); - } - return resolvedNames; + return configFileNames.map(resolveProjectName); } function buildAllProjects(): ExitStatus { @@ -1300,6 +1270,14 @@ namespace ts { } } + export function resolveConfigFileProjectName(project: string): ResolvedConfigFileName { + if (fileExtensionIs(project, Extension.Json)) { + return project as ResolvedConfigFileName; + } + + return combinePaths(project, "tsconfig.json") as ResolvedConfigFileName; + } + export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray { if (project.options.outFile) { return getOutFileOutputs(project); diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index 6d6f95ce19c..bb620fc776b 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -199,7 +199,7 @@ namespace ts { tick(); touch(fs, "/src/logic/index.ts"); // Because we haven't reset the build context, the builder should assume there's nothing to do right now - const status = builder.getUpToDateStatusOfFile(builder.resolveProjectName("/src/logic")!); + const status = builder.getUpToDateStatusOfFile(builder.resolveProjectName("/src/logic")); assert.equal(status.type, UpToDateStatusType.UpToDate, "Project should be assumed to be up-to-date"); // Rebuild this project diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index d3966071265..523fcefd88c 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -165,7 +165,7 @@ namespace ts { } function performBuild(args: string[]): number | undefined { - const { buildOptions, projects: buildProjects, errors } = parseBuildCommand(args); + const { buildOptions, projects, errors } = parseBuildCommand(args); if (errors.length > 0) { errors.forEach(reportDiagnostic); return ExitStatus.DiagnosticsPresent_OutputsSkipped; @@ -179,16 +179,6 @@ namespace ts { // Update to pretty if host supports it updateReportDiagnostic(); - const projects = mapDefined(buildProjects, project => { - const fileName = resolvePath(sys.getCurrentDirectory(), project); - const refPath = resolveProjectReferencePath(sys, { path: fileName }); - if (!sys.fileExists(refPath)) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_does_not_exist, fileName)); - return undefined; - } - return refPath; - }); - if (projects.length === 0) { printVersion(); printHelp(buildOpts, "--build "); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a2fbf9ac944..1202a0847b6 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4182,14 +4182,11 @@ declare namespace ts { * @returns A 'Program' object. */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; - interface ResolveProjectReferencePathHost { - fileExists(fileName: string): boolean; - } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ - function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; + function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { interface EmitOutput { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 6ab352033f3..18293f58e0a 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4182,14 +4182,11 @@ declare namespace ts { * @returns A 'Program' object. */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; - interface ResolveProjectReferencePathHost { - fileExists(fileName: string): boolean; - } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ - function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; + function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { interface EmitOutput {