mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-12 20:25:48 -06:00
Create folders for sys.writeFile if folder doesn't exist (#10848)
* Create folders for sys.writeFile * Use project root path for emit output file name * Normalize project file path for external projects * Patch writeFile for all sys implementations * Use the original file for single inferred project case * recursive create directory for all sys implementations
This commit is contained in:
parent
2ca9953235
commit
3c20df5e93
@ -583,19 +583,40 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
function recursiveCreateDirectory(directoryPath: string, sys: System) {
|
||||
const basePath = getDirectoryPath(directoryPath);
|
||||
const shouldCreateParent = directoryPath !== basePath && !sys.directoryExists(basePath);
|
||||
if (shouldCreateParent) {
|
||||
recursiveCreateDirectory(basePath, sys);
|
||||
}
|
||||
if (shouldCreateParent || !sys.directoryExists(directoryPath)) {
|
||||
sys.createDirectory(directoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
let sys: System;
|
||||
if (typeof ChakraHost !== "undefined") {
|
||||
return getChakraSystem();
|
||||
sys = getChakraSystem();
|
||||
}
|
||||
else if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") {
|
||||
return getWScriptSystem();
|
||||
sys = getWScriptSystem();
|
||||
}
|
||||
else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") {
|
||||
// process and process.nextTick checks if current environment is node-like
|
||||
// process.browser check excludes webpack and browserify
|
||||
return getNodeSystem();
|
||||
sys = getNodeSystem();
|
||||
}
|
||||
else {
|
||||
return undefined; // Unsupported host
|
||||
if (sys) {
|
||||
// patch writefile to create folder before writing the file
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = function(path, data, writeBom) {
|
||||
const directoryPath = getDirectoryPath(normalizeSlashes(path));
|
||||
if (!sys.directoryExists(directoryPath)) {
|
||||
recursiveCreateDirectory(directoryPath, sys);
|
||||
}
|
||||
originalWriteFile.call(sys, path, data, writeBom);
|
||||
};
|
||||
}
|
||||
return sys;
|
||||
})();
|
||||
}
|
||||
|
||||
@ -140,8 +140,10 @@ namespace ts.server {
|
||||
|
||||
const { emitSkipped, outputFiles } = this.project.getFileEmitOutput(fileInfo.scriptInfo, /*emitOnlyDtsFiles*/ false);
|
||||
if (!emitSkipped) {
|
||||
const projectRootPath = this.project.getProjectRootPath();
|
||||
for (const outputFile of outputFiles) {
|
||||
writeFile(outputFile.name, outputFile.text, outputFile.writeByteOrderMark);
|
||||
const outputFileAbsoluteFileName = getNormalizedAbsolutePath(outputFile.name, projectRootPath ? projectRootPath : getDirectoryPath(scriptInfo.fileName));
|
||||
writeFile(outputFileAbsoluteFileName, outputFile.text, outputFile.writeByteOrderMark);
|
||||
}
|
||||
}
|
||||
return !emitSkipped;
|
||||
|
||||
@ -183,7 +183,7 @@ namespace ts.server {
|
||||
constructor(public readonly host: ServerHost,
|
||||
public readonly logger: Logger,
|
||||
public readonly cancellationToken: HostCancellationToken,
|
||||
private readonly useSingleInferredProject: boolean,
|
||||
public readonly useSingleInferredProject: boolean,
|
||||
readonly typingsInstaller: ITypingsInstaller = nullTypingsInstaller,
|
||||
private readonly eventHandler?: ProjectServiceEventHandler) {
|
||||
|
||||
|
||||
@ -143,6 +143,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
abstract getProjectName(): string;
|
||||
abstract getProjectRootPath(): string | undefined;
|
||||
abstract getTypingOptions(): TypingOptions;
|
||||
|
||||
getSourceFile(path: Path) {
|
||||
@ -537,6 +538,15 @@ namespace ts.server {
|
||||
return this.inferredProjectName;
|
||||
}
|
||||
|
||||
getProjectRootPath() {
|
||||
// Single inferred project does not have a project root.
|
||||
if (this.projectService.useSingleInferredProject) {
|
||||
return undefined;
|
||||
}
|
||||
const rootFiles = this.getRootFiles();
|
||||
return getDirectoryPath(rootFiles[0]);
|
||||
}
|
||||
|
||||
close() {
|
||||
super.close();
|
||||
|
||||
@ -574,6 +584,10 @@ namespace ts.server {
|
||||
super(ProjectKind.Configured, projectService, documentRegistry, hasExplicitListOfFiles, languageServiceEnabled, compilerOptions, compileOnSaveEnabled);
|
||||
}
|
||||
|
||||
getProjectRootPath() {
|
||||
return getDirectoryPath(this.configFileName);
|
||||
}
|
||||
|
||||
setProjectErrors(projectErrors: Diagnostic[]) {
|
||||
this.projectErrors = projectErrors;
|
||||
}
|
||||
@ -662,10 +676,21 @@ namespace ts.server {
|
||||
documentRegistry: ts.DocumentRegistry,
|
||||
compilerOptions: CompilerOptions,
|
||||
languageServiceEnabled: boolean,
|
||||
public compileOnSaveEnabled: boolean) {
|
||||
public compileOnSaveEnabled: boolean,
|
||||
private readonly projectFilePath?: string) {
|
||||
super(ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, languageServiceEnabled, compilerOptions, compileOnSaveEnabled);
|
||||
}
|
||||
|
||||
getProjectRootPath() {
|
||||
if (this.projectFilePath) {
|
||||
return getDirectoryPath(this.projectFilePath);
|
||||
}
|
||||
// if the projectFilePath is not given, we make the assumption that the project name
|
||||
// is the path of the project file. AS the project name is provided by VS, we need to
|
||||
// normalize slashes before using it as a file name.
|
||||
return getDirectoryPath(normalizeSlashes(this.externalProjectName));
|
||||
}
|
||||
|
||||
getTypingOptions() {
|
||||
return this.typingOptions;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user