Browse Source

- hook in project unload trigger so the state of the language service will get reset.
- implemented caching of files, but it does not seem to have any effect on the compilation speed

Shaddock Heath 10 years ago
parent
commit
81188d913e

+ 41 - 3
Script/AtomicEditor/extensionServices/EditorExtensionServices.ts

@@ -31,8 +31,11 @@ export interface EditorService {
 }
 
 export interface ResourceService extends EditorService {
-    save(ev: EditorEvents.SaveResourceEvent);
-    canSave(ev: EditorEvents.SaveResourceEvent);
+    save?(ev: EditorEvents.SaveResourceEvent);
+    canSave?(ev: EditorEvents.SaveResourceEvent);
+    projectUnloaded?();
+    canDelete?();
+    delete?();
 }
 
 /**
@@ -54,6 +57,7 @@ class ServiceRegistry<T extends EditorService> {
  * Registry for service extensions that are concerned about Resources
  */
 class ResourceServiceRegistry extends ServiceRegistry<ResourceService> {
+
     saveResource(ev: EditorEvents.SaveResourceEvent) {
         // run through and find any services that can handle this.
         this.registeredServices.forEach((service) => {
@@ -62,7 +66,41 @@ class ResourceServiceRegistry extends ServiceRegistry<ResourceService> {
                 try {
                     service.save(ev);
                 } catch (e) {
-                    EditorUI.showModalError("Extension Error", `Error detected in extension ${service.name}\n ${e}`);
+                    EditorUI.showModalError("Extension Error", `Error detected in extension ${service.name}\n ${e}\n ${e.stack}`);
+                }
+            }
+        });
+    }
+
+    /**
+     * Called when a resource is being deleted
+     * @return {[type]} [description]
+     */
+    deleteResource() {
+        this.registeredServices.forEach((service) => {
+            // Verify that the service contains the appropriate methods and that it can save
+            if (service.canDelete && service.delete && service.canDelete()) {
+                try {
+                    service.delete();
+                } catch (e) {
+                    EditorUI.showModalError("Extension Error", `Error detected in extension ${service.name}\n ${e}\n ${e.stack}`);
+                }
+            }
+        });
+    }
+
+    /**
+     * Called when the project is unloaded
+     * @param  {[type]} data Event info from the project unloaded event
+     */
+    projectUnloaded(data) {
+        this.registeredServices.forEach((service) => {
+            // Verify that the service contains the appropriate methods and that it can save
+            if (service.projectUnloaded) {
+                try {
+                    service.projectUnloaded();
+                } catch (e) {
+                    EditorUI.showModalError("Extension Error", `Error detected in extension ${service.name}\n ${e}\n ${e.stack}`);
                 }
             }
         });

+ 44 - 7
Script/AtomicEditor/extensionServices/resourceServices/TypescriptLanguageService.ts

@@ -4,7 +4,6 @@
 // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
 // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
 //
-
 // Based upon the TypeScript language services example at https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
 
 import * as ExtensionServices from "../EditorExtensionServices";
@@ -20,7 +19,7 @@ export default class TypescriptLanguageService implements ExtensionServices.Reso
 
     languageService: ts.LanguageService;
     projectFiles: string[];
-    versionMap: ts.Map<{ version: number }> = {};
+    versionMap: ts.Map<{ version: number, snapshot?: ts.IScriptSnapshot }> = {};
 
     /**
      * Perform a full compile on save, or just transpile the current file
@@ -119,14 +118,34 @@ export default class TypescriptLanguageService implements ExtensionServices.Reso
                 getScriptFileNames: () => this.projectFiles,
                 getScriptVersion: (fileName) => this.versionMap[fileName] && this.versionMap[fileName].version.toString(),
                 getScriptSnapshot: (fileName) => {
+                    const scriptVersion = this.versionMap[fileName];
                     if (!Atomic.fileSystem.exists(fileName)) {
+                        if (scriptVersion) {
+                            delete this.versionMap[fileName];
+                            let idx = this.projectFiles.indexOf(fileName);
+                            if (idx > -1) {
+                                this.projectFiles.splice(idx, 1);
+                            }
+                        }
                         return undefined;
                     }
-                    let script = new Atomic.File(fileName, Atomic.FILE_READ);
-                    try {
-                        return ts.ScriptSnapshot.fromString(script.readText());
-                    } finally {
-                        script.close();
+
+                    // Grab the cached version
+                    if (scriptVersion) {
+                        if (scriptVersion.snapshot) {
+                            console.log(`cache hit snapshot for ${fileName}`);
+                            return scriptVersion.snapshot;
+                        } else {
+                            let script = new Atomic.File(fileName, Atomic.FILE_READ);
+                            try {
+                                scriptVersion.snapshot = ts.ScriptSnapshot.fromString(script.readText());
+                                return scriptVersion.snapshot;
+                            } finally {
+                                script.close();
+                            }
+                        }
+                    } else {
+                        console.log(`no script version for ${fileName}`);
                     }
                 },
                 getCurrentDirectory: () => ToolCore.toolSystem.project.resourcePath,
@@ -146,6 +165,7 @@ export default class TypescriptLanguageService implements ExtensionServices.Reso
             files.forEach(filename => {
                 // increment the version number since we changed
                 this.versionMap[filename].version++;
+                this.versionMap[filename].snapshot = null;
                 errors = errors.concat(this.compileFile(filename));
             });
         }
@@ -222,6 +242,14 @@ export default class TypescriptLanguageService implements ExtensionServices.Reso
         throw new Error(`TypeScript Errors:\n${msg.join("\n") }`);
     }
 
+    /**
+     * clear out any caches, etc.
+     */
+    resetLanguageService() {
+        this.projectFiles = null;
+        this.versionMap = {};
+    }
+
     /**
      * Inject this language service into the registry
      * @return {[type]}             True if successful
@@ -255,6 +283,15 @@ export default class TypescriptLanguageService implements ExtensionServices.Reso
         }
     }
 
+    /**
+     * Called when the project is being unloaded to allow the typscript language service to reset
+     */
+    projectUnloaded() {
+        // got an unload, we need to reset the language service
+        console.log(`${this.name}: received a project unloaded event`);
+        this.resetLanguageService();
+    }
+
     /**
      * Can this service extension handle the save event for the resource?
      * @param  {EditorEvents.SaveResourceEvent} ev the

+ 4 - 1
Script/AtomicEditor/ui/frames/ResourceFrame.ts

@@ -58,7 +58,7 @@ class ResourceFrame extends ScriptWidget {
             this.currentResourceEditor.save();
             // Grab the path to this file and pass it to the save resource
             ServiceLocator.resourceServices.saveResource({
-                path: this.currentResourceEditor.fullPath,
+                path: ev.path || this.currentResourceEditor.fullPath,
             });
         }
 
@@ -258,6 +258,9 @@ class ResourceFrame extends ScriptWidget {
           this.editors[i].close();
       }
 
+      // tell extensions that the project has been unloaded
+      ServiceLocator.resourceServices.projectUnloaded(data);
+
     }
 
     constructor(parent: Atomic.UIWidget) {