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:
Zhengbo Li 2016-09-13 16:20:42 -07:00 committed by GitHub
parent 2ca9953235
commit 3c20df5e93
4 changed files with 56 additions and 8 deletions

View File

@ -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;
})();
}

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}