Forráskód Böngészése

Added functionality to pull in a custom compiler options block if there is a tsconfig.json in the root of the project. Also updated the output to show compiler settings and time to compile.

Shaddock Heath 9 éve
szülő
commit
2d440da91a

+ 46 - 7
Script/AtomicEditor/hostExtensions/languageExtensions/TypscriptLanguageExtension.ts

@@ -22,6 +22,24 @@
 
 
 import * as EditorEvents from "../../editor/EditorEvents";
 import * as EditorEvents from "../../editor/EditorEvents";
 
 
+/**
+ * Default compiler options to use for compilation.  If there
+ * is a compiler option block in a tsconfig.json located in the project,
+ * then the one in the project will overwrite these
+ * @type {ts.CompilerOptions}
+ */
+const defaultCompilerOptions = {
+    noEmitOnError: true,
+    noImplicitAny: false,
+    target: "es5",
+    module: "commonjs",
+    moduleResolution: "classic",
+    declaration: false,
+    inlineSourceMap: false,
+    removeComments: false,
+    noLib: true
+};
+
 /**
 /**
  * Resource extension that supports the web view typescript extension
  * Resource extension that supports the web view typescript extension
  */
  */
@@ -63,6 +81,8 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
         if (this.isTypescriptProject) {
         if (this.isTypescriptProject) {
             let projectFiles: Array<string> = [];
             let projectFiles: Array<string> = [];
 
 
+            let compilerOptions = defaultCompilerOptions;
+
             //scan all the files in the project for any typescript files and add them to the project
             //scan all the files in the project for any typescript files and add them to the project
             Atomic.fileSystem.scanDir(ToolCore.toolSystem.project.resourcePath, "*.ts", Atomic.SCAN_FILES, true).forEach(filename => {
             Atomic.fileSystem.scanDir(ToolCore.toolSystem.project.resourcePath, "*.ts", Atomic.SCAN_FILES, true).forEach(filename => {
                 projectFiles.push(Atomic.addTrailingSlash(ToolCore.toolSystem.project.resourcePath) + filename);
                 projectFiles.push(Atomic.addTrailingSlash(ToolCore.toolSystem.project.resourcePath) + filename);
@@ -96,6 +116,11 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
                             }
                             }
                         });
                         });
                     }
                     }
+
+                    // override the default options if the tsconfig contains them
+                    if (savedTsConfig["compilerOptions"]) {
+                        compilerOptions = savedTsConfig["compilerOptions"];
+                    }
                 } finally {
                 } finally {
                     file.close();
                     file.close();
                 }
                 }
@@ -115,6 +140,7 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
             }
             }
 
 
             let tsConfig = {
             let tsConfig = {
+                compilerOptions: compilerOptions,
                 files: projectFiles
                 files: projectFiles
             };
             };
             return tsConfig;
             return tsConfig;
@@ -277,7 +303,7 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
     handleWebMessage(messageType: string, data: any) {
     handleWebMessage(messageType: string, data: any) {
         switch (messageType) {
         switch (messageType) {
             case "TypeScript.DisplayCompileResults":
             case "TypeScript.DisplayCompileResults":
-                this.displayCompileResults(data.annotations);
+                this.displayCompileResults(data);
                 break;
                 break;
         }
         }
     }
     }
@@ -327,11 +353,14 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
      * Display the results of the compilation step
      * Display the results of the compilation step
      * @param  {any[]} annotations
      * @param  {any[]} annotations
      */
      */
-    displayCompileResults(annotations: any[]) {
+    displayCompileResults(results: {
+        annotations: any[],
+        compilerOptions: any,
+        duration: number
+    }) {
         // get the name of the resources directory without preceding path
         // get the name of the resources directory without preceding path
         let resourceDir = ToolCore.toolSystem.project.resourcePath.replace(Atomic.addTrailingSlash(ToolCore.toolSystem.project.projectPath), "");
         let resourceDir = ToolCore.toolSystem.project.resourcePath.replace(Atomic.addTrailingSlash(ToolCore.toolSystem.project.projectPath), "");
-        console.log(resourceDir);
-        let messageArray = annotations.filter(result => {
+        let messageArray = results.annotations.filter(result => {
             // If we are compiling the lib.d.ts or some other built-in library and it was successful, then
             // If we are compiling the lib.d.ts or some other built-in library and it was successful, then
             // we really don't need to display that result since it's just noise.  Only display it if it fails
             // we really don't need to display that result since it's just noise.  Only display it if it fails
             if (result.type == "success") {
             if (result.type == "success") {
@@ -349,11 +378,21 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
                 message += `<color #e3e02b>${result.text} at line ${result.row} col ${result.column}</color>`;
                 message += `<color #e3e02b>${result.text} at line ${result.row} col ${result.column}</color>`;
             }
             }
             return message;
             return message;
-        });
+        }).join("\n");
 
 
         if (messageArray.length == 0) {
         if (messageArray.length == 0) {
-            messageArray.push("Success");
+            messageArray = "Success";
         }
         }
-        this.serviceRegistry.uiServices.showModalError("TypeScript Compilation Results", messageArray.join("\n"));
+
+        let message = [
+            "Compiler Options: ",
+            JSON.stringify(results.compilerOptions, null, 2),
+            "",
+            messageArray,
+            "",
+            `Compilation Completed in ${results.duration}ms`
+        ].join("\n");
+
+        this.serviceRegistry.uiServices.showModalError("TypeScript Compilation Results", message);
     }
     }
 }
 }

+ 18 - 15
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/TypescriptLanguageExtension.ts

@@ -97,7 +97,7 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
      * Grabs the TS Config file attached to the global window object
      * Grabs the TS Config file attached to the global window object
      * @return {any}
      * @return {any}
      */
      */
-    private getTsConfig():any {
+    private getTsConfig(): any {
         return JSON.parse(window["TypeScriptLanguageExtension"]["tsConfig"]);
         return JSON.parse(window["TypeScriptLanguageExtension"]["tsConfig"]);
     }
     }
 
 
@@ -273,7 +273,6 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
                 filename: ev.filename,
                 filename: ev.filename,
                 fileExt: ev.fileExt,
                 fileExt: ev.fileExt,
                 code: ev.code,
                 code: ev.code,
-                tsConfig: this.getTsConfig(),
                 editor: null // cannot send editor across the boundary
                 editor: null // cannot send editor across the boundary
             };
             };
 
 
@@ -323,26 +322,30 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
      * @return {[type]}
      * @return {[type]}
      */
      */
     preferencesChanged() {
     preferencesChanged() {
-        let compileOnSave = this.serviceLocator.clientServices.getUserPreference("HostTypeScriptLanguageExtension", "CompileOnSave", true);
-        const message: WorkerProcessTypes.SetPreferencesMessageData = {
-            command: WorkerProcessTypes.SetPreferences,
-            preferences: {
-                compileOnSave: compileOnSave
-            }
-        };
+        if (this.worker) {
+            let compileOnSave = this.serviceLocator.clientServices.getUserPreference("HostTypeScriptLanguageExtension", "CompileOnSave", true);
+            const message: WorkerProcessTypes.SetPreferencesMessageData = {
+                command: WorkerProcessTypes.SetPreferences,
+                preferences: {
+                    compileOnSave: compileOnSave
+                }
+            };
 
 
-        this.worker.port.postMessage(message);
+            this.worker.port.postMessage(message);
+        }
     }
     }
 
 
     /**
     /**
      * Tell the language service to perform a full compile
      * Tell the language service to perform a full compile
      */
      */
     doFullCompile() {
     doFullCompile() {
-        const message: WorkerProcessTypes.FullCompileMessageData = {
-            command: WorkerProcessTypes.DoFullCompile,
-            tsConfig: this.getTsConfig()
-        };
-        this.worker.port.postMessage(message);
+        if (this.worker) {
+            const message: WorkerProcessTypes.FullCompileMessageData = {
+                command: WorkerProcessTypes.DoFullCompile,
+                tsConfig: this.getTsConfig()
+            };
+            this.worker.port.postMessage(message);
+        }
     }
     }
 
 
 
 

+ 9 - 23
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/TypescriptLanguageService.ts

@@ -59,8 +59,9 @@ export interface FileSystemInterface {
  */
  */
 export class TypescriptLanguageService {
 export class TypescriptLanguageService {
 
 
-    constructor(fs: FileSystemInterface) {
+    constructor(fs: FileSystemInterface, compilerOptions: ts.CompilerOptions) {
         this.fs = fs;
         this.fs = fs;
+        this.compilerOptions = compilerOptions;
 
 
         // Create the language service files
         // Create the language service files
         this.documentRegistry = ts.createDocumentRegistry();
         this.documentRegistry = ts.createDocumentRegistry();
@@ -71,13 +72,7 @@ export class TypescriptLanguageService {
     private languageService: ts.LanguageService = null;
     private languageService: ts.LanguageService = null;
     private documentRegistry: ts.DocumentRegistry = null;
     private documentRegistry: ts.DocumentRegistry = null;
 
 
-    public compilerOptions: ts.CompilerOptions = {
-        noEmitOnError: true,
-        noImplicitAny: false,
-        target: ts.ScriptTarget.ES5,
-        module: ts.ModuleKind.CommonJS,
-        noLib: true
-    };
+    public compilerOptions: ts.CompilerOptions = null;
 
 
     name: string = "TypescriptLanguageService";
     name: string = "TypescriptLanguageService";
 
 
@@ -91,7 +86,6 @@ export class TypescriptLanguageService {
     private versionMap: ts.Map<{ version: number, snapshot?: ts.IScriptSnapshot }> = {};
     private versionMap: ts.Map<{ version: number, snapshot?: ts.IScriptSnapshot }> = {};
 
 
     private createLanguageService(documentRegistry: ts.DocumentRegistry) {
     private createLanguageService(documentRegistry: ts.DocumentRegistry) {
-
         // Create the language service host to allow the LS to communicate with the host
         // Create the language service host to allow the LS to communicate with the host
         const servicesHost: ts.LanguageServiceHost = {
         const servicesHost: ts.LanguageServiceHost = {
             getScriptFileNames: () => this.projectFiles,
             getScriptFileNames: () => this.projectFiles,
@@ -104,7 +98,6 @@ export class TypescriptLanguageService {
                     if (scriptVersion.snapshot) {
                     if (scriptVersion.snapshot) {
                         return scriptVersion.snapshot;
                         return scriptVersion.snapshot;
                     } else {
                     } else {
-                        console.log(`!!! creating snapshot for ${filename}`);
                         let sourceFile = this.documentRegistry.acquireDocument(filename, this.compilerOptions, ts.ScriptSnapshot.fromString(""), scriptVersion.version.toString());
                         let sourceFile = this.documentRegistry.acquireDocument(filename, this.compilerOptions, ts.ScriptSnapshot.fromString(""), scriptVersion.version.toString());
                         return ts.ScriptSnapshot.fromString(sourceFile.text);
                         return ts.ScriptSnapshot.fromString(sourceFile.text);
                     }
                     }
@@ -163,6 +156,7 @@ export class TypescriptLanguageService {
      */
      */
     updateProjectFileVersionNumber(filename: string): ts.SourceFile {
     updateProjectFileVersionNumber(filename: string): ts.SourceFile {
         this.versionMap[filename].version++;
         this.versionMap[filename].version++;
+
         return this.documentRegistry.updateDocument(
         return this.documentRegistry.updateDocument(
             filename,
             filename,
             this.compilerOptions,
             this.compilerOptions,
@@ -177,9 +171,7 @@ export class TypescriptLanguageService {
         return this.projectFiles;
         return this.projectFiles;
     }
     }
 
 
-    getPreEmitWarnings(filename: string, options?: ts.CompilerOptions) {
-        options = options || this.compilerOptions;
-
+    getPreEmitWarnings(filename: string) {
         let allDiagnostics = this.compileFile(filename);
         let allDiagnostics = this.compileFile(filename);
         let results = [];
         let results = [];
 
 
@@ -199,17 +191,13 @@ export class TypescriptLanguageService {
     /**
     /**
      * Simply transpile the typescript file.  This is much faster and only checks for syntax errors
      * Simply transpile the typescript file.  This is much faster and only checks for syntax errors
      * @param {string[]}           fileNames array of files to transpile
      * @param {string[]}           fileNames array of files to transpile
-     * @param {ts.CompilerOptions} options   compiler options
      */
      */
-    transpile(fileNames: string[], options?: ts.CompilerOptions): void {
-        options = options || this.compilerOptions;
-        this.compilerOptions = options;
-
+    transpile(fileNames: string[]): void {
         fileNames.forEach((fileName) => {
         fileNames.forEach((fileName) => {
             console.log(`${this.name}:  Transpiling ${fileName}`);
             console.log(`${this.name}:  Transpiling ${fileName}`);
             let script = this.fs.getFile(fileName);
             let script = this.fs.getFile(fileName);
             let diagnostics: ts.Diagnostic[] = [];
             let diagnostics: ts.Diagnostic[] = [];
-            let result = ts.transpile(script, options, fileName, diagnostics);
+            let result = ts.transpile(script, this.compilerOptions, fileName, diagnostics);
             if (diagnostics.length) {
             if (diagnostics.length) {
                 this.logErrors(diagnostics);
                 this.logErrors(diagnostics);
             }
             }
@@ -250,16 +238,14 @@ export class TypescriptLanguageService {
     getCompletionEntryDetails(filename: string, pos: number, entryname: string): ts.CompletionEntryDetails {
     getCompletionEntryDetails(filename: string, pos: number, entryname: string): ts.CompletionEntryDetails {
         return this.languageService.getCompletionEntryDetails(filename, pos, entryname);
         return this.languageService.getCompletionEntryDetails(filename, pos, entryname);
     }
     }
-    
+
     /**
     /**
      * Compile the provided file to javascript with full type checking etc
      * Compile the provided file to javascript with full type checking etc
      * @param  {string}  a list of file names to compile
      * @param  {string}  a list of file names to compile
-     * @param  {ts.CompilerOptions} options for the compiler
      * @param  {function} optional callback which will be called for every file compiled and will provide any errors
      * @param  {function} optional callback which will be called for every file compiled and will provide any errors
      */
      */
-    compile(files: string[], options?: ts.CompilerOptions, progress?: (filename: string, errors: ts.Diagnostic[]) => void): ts.Diagnostic[] {
+    compile(files: string[], progress?: (filename: string, errors: ts.Diagnostic[]) => void): ts.Diagnostic[] {
         let start = new Date().getTime();
         let start = new Date().getTime();
-        options = options || this.compilerOptions;
 
 
         //Make sure we have these files in the project
         //Make sure we have these files in the project
         files.forEach((file) => {
         files.forEach((file) => {

+ 15 - 10
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/TypescriptLanguageServiceWebWorker.ts

@@ -121,8 +121,7 @@ class WebFileSystem implements FileSystemInterface {
                 filename: filename,
                 filename: filename,
                 code: contents,
                 code: contents,
                 fileExt: fileExt,
                 fileExt: fileExt,
-                editor: null,
-                tsConfig: null
+                editor: null
             };
             };
 
 
             this.communicationPort.postMessage(message);
             this.communicationPort.postMessage(message);
@@ -164,7 +163,6 @@ export default class TypescriptLanguageServiceWebWorker {
 
 
     constructor() {
     constructor() {
         this.fs = new WebFileSystem();
         this.fs = new WebFileSystem();
-        this.languageService = new TypescriptLanguageService(this.fs);
     }
     }
 
 
     /**
     /**
@@ -236,10 +234,6 @@ export default class TypescriptLanguageServiceWebWorker {
         // and delete any that may be been removed and sync up
         // and delete any that may be been removed and sync up
         let promises: PromiseLike<void>[] = [];
         let promises: PromiseLike<void>[] = [];
 
 
-        if (this.tsConfig.compilerOptions) {
-            this.languageService.compilerOptions = this.tsConfig.compilerOptions;
-        };
-
         let existingFiles = this.languageService.getProjectFiles();
         let existingFiles = this.languageService.getProjectFiles();
 
 
         // see if anything was deleted
         // see if anything was deleted
@@ -275,6 +269,9 @@ export default class TypescriptLanguageServiceWebWorker {
     }) {
     }) {
         //port.postMessage({ command: WorkerProcessTypes.Message, message: "Hello " + eventData.sender + " (port #" + this.connections + ")" });
         //port.postMessage({ command: WorkerProcessTypes.Message, message: "Hello " + eventData.sender + " (port #" + this.connections + ")" });
         this.tsConfig = eventData.tsConfig;
         this.tsConfig = eventData.tsConfig;
+        if (!this.languageService) {
+            this.languageService = new TypescriptLanguageService(this.fs, this.tsConfig.compilerOptions);
+        }
 
 
         // Check to see if the file coming in is already in the
         // Check to see if the file coming in is already in the
         // tsconfig.  The file coming in won't have a full path
         // tsconfig.  The file coming in won't have a full path
@@ -388,7 +385,6 @@ export default class TypescriptLanguageServiceWebWorker {
      * @param  {WorkerProcessCommands.SaveMessageData} eventData
      * @param  {WorkerProcessCommands.SaveMessageData} eventData
      */
      */
     handleSave(port: MessagePort, eventData: WorkerProcessTypes.SaveMessageData) {
     handleSave(port: MessagePort, eventData: WorkerProcessTypes.SaveMessageData) {
-        this.tsConfig = eventData.tsConfig;
         let filename = this.resolvePartialFilename(eventData.filename);
         let filename = this.resolvePartialFilename(eventData.filename);
 
 
         this.languageService.updateProjectFile(filename, eventData.code);
         this.languageService.updateProjectFile(filename, eventData.code);
@@ -407,6 +403,11 @@ export default class TypescriptLanguageServiceWebWorker {
      */
      */
     doFullCompile(port: MessagePort, eventData: WorkerProcessTypes.FullCompileMessageData) {
     doFullCompile(port: MessagePort, eventData: WorkerProcessTypes.FullCompileMessageData) {
         this.tsConfig = eventData.tsConfig;
         this.tsConfig = eventData.tsConfig;
+        this.languageService.compilerOptions = this.tsConfig.compilerOptions;
+        if (eventData.tsConfig.compilerOptions) {
+            this.languageService.compilerOptions = eventData.tsConfig.compilerOptions;
+        }
+
         this.fs.setCommunicationPort(port);
         this.fs.setCommunicationPort(port);
 
 
         // update all the files
         // update all the files
@@ -415,7 +416,8 @@ export default class TypescriptLanguageServiceWebWorker {
         });
         });
 
 
         let results = [];
         let results = [];
-        this.languageService.compile([], this.languageService.compilerOptions, (filename, errors) => {
+        let start = Date.now();
+        this.languageService.compile([], (filename, errors) => {
             if (errors.length > 0) {
             if (errors.length > 0) {
                 results = results.concat(errors.map(diagnostic => {
                 results = results.concat(errors.map(diagnostic => {
                     let lineChar = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
                     let lineChar = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
@@ -438,10 +440,13 @@ export default class TypescriptLanguageServiceWebWorker {
                 });
                 });
             }
             }
         });
         });
+        let duration = Date.now() - start;
 
 
         let message: WorkerProcessTypes.FullCompileResultsMessageData = {
         let message: WorkerProcessTypes.FullCompileResultsMessageData = {
             command: WorkerProcessTypes.DisplayFullCompileResults,
             command: WorkerProcessTypes.DisplayFullCompileResults,
-            annotations: results
+            annotations: results,
+            compilerOptions: this.languageService.compilerOptions,
+            duration: duration
         };
         };
         this.fs.setCommunicationPort(null);
         this.fs.setCommunicationPort(null);
         port.postMessage(message);
         port.postMessage(message);

+ 5 - 4
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/workerProcessTypes.ts

@@ -28,9 +28,7 @@ export interface WorkerProcessMessageData {
     command: string;
     command: string;
 }
 }
 
 
-export interface SaveMessageData extends WorkerProcessMessageData, Editor.EditorEvents.CodeSavedEvent {
-    tsConfig: any
-}
+export interface SaveMessageData extends WorkerProcessMessageData, Editor.EditorEvents.CodeSavedEvent {}
 
 
 export interface DeleteMessageData extends WorkerProcessMessageData, Editor.EditorEvents.DeleteResourceEvent { }
 export interface DeleteMessageData extends WorkerProcessMessageData, Editor.EditorEvents.DeleteResourceEvent { }
 export interface RenameMessageData extends WorkerProcessMessageData, Editor.EditorEvents.RenameResourceEvent { }
 export interface RenameMessageData extends WorkerProcessMessageData, Editor.EditorEvents.RenameResourceEvent { }
@@ -92,7 +90,10 @@ export interface FullCompileMessageData extends WorkerProcessMessageData {
 };
 };
 
 
 export const DisplayFullCompileResults = "DISPLAY_FULL_COMPILE_RESULTS";
 export const DisplayFullCompileResults = "DISPLAY_FULL_COMPILE_RESULTS";
-export interface FullCompileResultsMessageData extends GetAnnotationsResponseMessageData { }
+export interface FullCompileResultsMessageData extends GetAnnotationsResponseMessageData {
+    compilerOptions: any;
+    duration: number;
+}
 
 
 export const SaveFile = "SAVE_FILE";
 export const SaveFile = "SAVE_FILE";