Browse Source

Work on routing delete, rename, and project unloaded events to the web view so that the typescript language service can keep it's internal representation of the project in sync

Shaddock Heath 9 years ago
parent
commit
bcb4cf18bf

+ 2 - 1
Script/AtomicEditor/editor/Editor.ts

@@ -63,7 +63,7 @@ class Editor extends Atomic.ScriptObject {
 
 
         this.subscribeToEvent(EditorEvents.LoadProject, (data) => this.handleEditorLoadProject(data));
         this.subscribeToEvent(EditorEvents.LoadProject, (data) => this.handleEditorLoadProject(data));
         this.subscribeToEvent(EditorEvents.CloseProject, (data) => this.handleEditorCloseProject(data));
         this.subscribeToEvent(EditorEvents.CloseProject, (data) => this.handleEditorCloseProject(data));
-        this.subscribeToEvent("ProjectUnloaded", (data) => {
+        this.subscribeToEvent(EditorEvents.ProjectUnloadedNotification, (data) => {
             Atomic.graphics.windowTitle = "AtomicEditor";
             Atomic.graphics.windowTitle = "AtomicEditor";
             this.handleProjectUnloaded(data);
             this.handleProjectUnloaded(data);
         });
         });
@@ -175,6 +175,7 @@ class Editor extends Atomic.ScriptObject {
 
 
     handleEditorCloseProject(event) {
     handleEditorCloseProject(event) {
         this.projectCloseRequested = true;
         this.projectCloseRequested = true;
+        this.sendEvent(EditorEvents.ProjectUnloadedNotification, event);
         this.closeAllResourceEditors();
         this.closeAllResourceEditors();
     }
     }
 
 

+ 4 - 2
Script/AtomicEditor/editor/EditorEvents.ts

@@ -64,6 +64,7 @@ export interface ContentFolderChangedEvent {
 
 
 export const CloseProject = "EditorCloseProject";
 export const CloseProject = "EditorCloseProject";
 export const ProjectClosed = "EditorProjectClosed";
 export const ProjectClosed = "EditorProjectClosed";
+export const ProjectUnloadedNotification = "ProjectUnloadedNotification";
 
 
 export const LoadProject = "EditorLoadProject";
 export const LoadProject = "EditorLoadProject";
 export const LoadProjectNotification = "EditorLoadProjectNotification";
 export const LoadProjectNotification = "EditorLoadProjectNotification";
@@ -110,7 +111,7 @@ export const DeleteResource = "EditorDeleteResource";
  * Called once the resource has been deleted
  * Called once the resource has been deleted
  * @type {String}
  * @type {String}
  */
  */
-export const DeleteResourceNotification = "EditorDeleteResourceNotification";
+export const DeleteResourceNotification = "DeleteResourceNotification";
 export interface DeleteResourceEvent {
 export interface DeleteResourceEvent {
 
 
   // The full path to the resource to edit
   // The full path to the resource to edit
@@ -123,12 +124,13 @@ export const RenameResource = "EditorRenameResource";
  * Called once the resource has been renamed
  * Called once the resource has been renamed
  * @type {String}
  * @type {String}
  */
  */
-export const RenameResourceNotification = "EditorRenameResourceNotification";
+export const RenameResourceNotification = "RenameResourceNotification";
 export interface RenameResourceEvent {
 export interface RenameResourceEvent {
 
 
   // The full path to the resource to edit
   // The full path to the resource to edit
   path: string;
   path: string;
   newPath: string;
   newPath: string;
+  newName: string;
 
 
   // the asset to delete
   // the asset to delete
   asset: ToolCore.Asset;
   asset: ToolCore.Asset;

+ 26 - 3
Script/AtomicEditor/hostExtensions/languageExtensions/TypscriptLanguageExtension.ts

@@ -4,6 +4,7 @@
 // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
 // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
 // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
 // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
 //
 //
+import * as EditorEvents from "../../editor/EditorEvents";
 
 
 /**
 /**
  * Resource extension that supports the web view typescript extension
  * Resource extension that supports the web view typescript extension
@@ -17,7 +18,7 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
      * @type {Boolean}
      * @type {Boolean}
      */
      */
     private isTypescriptProject = false;
     private isTypescriptProject = false;
-
+    private serviceRegistry: Editor.HostExtensions.HostServiceLocator = null;
     /**
     /**
      * Determines if the file name/path provided is something we care about
      * Determines if the file name/path provided is something we care about
      * @param  {string} path
      * @param  {string} path
@@ -94,6 +95,7 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
         // We care about both resource events as well as project events
         // We care about both resource events as well as project events
         serviceRegistry.resourceServices.register(this);
         serviceRegistry.resourceServices.register(this);
         serviceRegistry.projectServices.register(this);
         serviceRegistry.projectServices.register(this);
+        this.serviceRegistry = serviceRegistry;
     }
     }
 
 
     /**
     /**
@@ -110,6 +112,15 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
             if (jsFileAsset) {
             if (jsFileAsset) {
                 console.log(`${this.name}: deleting corresponding .js file`);
                 console.log(`${this.name}: deleting corresponding .js file`);
                 ToolCore.assetDatabase.deleteAsset(jsFileAsset);
                 ToolCore.assetDatabase.deleteAsset(jsFileAsset);
+
+                let eventData: EditorEvents.DeleteResourceEvent = {
+                    path: jsFile
+                };
+
+                this.serviceRegistry.sendEvent(EditorEvents.DeleteResourceNotification, eventData);
+                
+                // rebuild the tsconfig.atomic
+                this.loadProjectFiles();
             }
             }
         }
         }
     }
     }
@@ -124,11 +135,23 @@ export default class TypescriptLanguageExtension implements Editor.HostExtension
 
 
             // Rename the corresponding js file
             // Rename the corresponding js file
             let jsFile = ev.path.replace(/\.ts$/, ".js");
             let jsFile = ev.path.replace(/\.ts$/, ".js");
-            let jsFileNew = ev.newPath.replace(/\.ts$/, ".js");
+            let jsFileNew = ev.newPath.replace(/\.ts$/, ".js"); // rename doesn't want extension
             let jsFileAsset = ToolCore.assetDatabase.getAssetByPath(jsFile);
             let jsFileAsset = ToolCore.assetDatabase.getAssetByPath(jsFile);
             if (jsFileAsset) {
             if (jsFileAsset) {
                 console.log(`${this.name}: renaming corresponding .js file`);
                 console.log(`${this.name}: renaming corresponding .js file`);
-                jsFileAsset.rename(jsFileNew);
+                jsFileAsset.rename(ev.newName);
+
+                let eventData: EditorEvents.RenameResourceEvent = {
+                    path: jsFile,
+                    newPath: jsFileNew,
+                    newName: ev.newName,
+                    asset: jsFileAsset
+                };
+
+                this.serviceRegistry.sendEvent(EditorEvents.RenameResourceNotification, eventData);
+
+                // rebuild the tsconfig.atomic
+                this.loadProjectFiles();
             }
             }
         }
         }
     }
     }

+ 2 - 1
Script/AtomicEditor/ui/frames/MainFrame.ts

@@ -34,6 +34,7 @@ import MainFrameMenu = require("./menus/MainFrameMenu");
 
 
 import MenuItemSources = require("./menus/MenuItemSources");
 import MenuItemSources = require("./menus/MenuItemSources");
 import ServiceLocator from "../../hostExtensions/ServiceLocator";
 import ServiceLocator from "../../hostExtensions/ServiceLocator";
+import * as EditorEvents from "../../editor/EditorEvents";
 
 
 class MainFrame extends ScriptWidget {
 class MainFrame extends ScriptWidget {
 
 
@@ -69,7 +70,7 @@ class MainFrame extends ScriptWidget {
             this.enableProjectMenus();
             this.enableProjectMenus();
         });
         });
 
 
-        this.subscribeToEvent("ProjectUnloaded", (data) => {
+        this.subscribeToEvent(EditorEvents.ProjectUnloadedNotification, (data) => {
             this.showWelcomeFrame(true);
             this.showWelcomeFrame(true);
             this.disableProjectMenus();
             this.disableProjectMenus();
         });
         });

+ 1 - 1
Script/AtomicEditor/ui/frames/ProjectFrame.ts

@@ -63,7 +63,7 @@ class ProjectFrame extends ScriptWidget {
 
 
         // events
         // events
         this.subscribeToEvent("ProjectLoaded", (data) => this.handleProjectLoaded(data));
         this.subscribeToEvent("ProjectLoaded", (data) => this.handleProjectLoaded(data));
-        this.subscribeToEvent("ProjectUnloaded", (data) => this.handleProjectUnloaded(data));
+        this.subscribeToEvent(EditorEvents.ProjectUnloadedNotification, (data) => this.handleProjectUnloaded(data));
         this.subscribeToEvent("DragEnded", (data: Atomic.DragEndedEvent) => this.handleDragEnded(data));
         this.subscribeToEvent("DragEnded", (data: Atomic.DragEndedEvent) => this.handleDragEnded(data));
 
 
         this.subscribeToEvent("ResourceAdded", (ev: ToolCore.ResourceAddedEvent) => this.handleResourceAdded(ev));
         this.subscribeToEvent("ResourceAdded", (ev: ToolCore.ResourceAddedEvent) => this.handleResourceAdded(ev));

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

@@ -63,6 +63,14 @@ class ResourceFrame extends ScriptWidget {
 
 
     }
     }
 
 
+    handleDeleteResource(ev: EditorEvents.DeleteResourceEvent) {
+        var editor = this.editors[ev.path];
+        if (editor) {
+            editor.close(true);
+            delete this.editors[ev.path];
+        }
+    }
+
     handleSaveAllResources(data) {
     handleSaveAllResources(data) {
 
 
         for (var i in this.editors) {
         for (var i in this.editors) {
@@ -210,6 +218,14 @@ class ResourceFrame extends ScriptWidget {
 
 
     }
     }
 
 
+    handleRenameResource(ev:EditorEvents.RenameResourceEvent) {
+        var editor = this.editors[ev.path];
+        if (editor) {
+            this.editors[ev.newPath] = editor;
+            delete this.editors[ev.path];
+        }
+    }
+
     handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
     handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
 
 
         if (ev.type == Atomic.UI_EVENT_TYPE_TAB_CHANGED && ev.target == this.tabcontainer) {
         if (ev.type == Atomic.UI_EVENT_TYPE_TAB_CHANGED && ev.target == this.tabcontainer) {
@@ -275,11 +291,13 @@ class ResourceFrame extends ScriptWidget {
 
 
         this.resourceViewContainer.addChild(this);
         this.resourceViewContainer.addChild(this);
 
 
-        this.subscribeToEvent("ProjectUnloaded", (data) => this.handleProjectUnloaded(data));
+        this.subscribeToEvent(EditorEvents.ProjectUnloadedNotification, (data) => this.handleProjectUnloaded(data));
         this.subscribeToEvent(EditorEvents.EditResource, (data) => this.handleEditResource(data));
         this.subscribeToEvent(EditorEvents.EditResource, (data) => this.handleEditResource(data));
         this.subscribeToEvent(EditorEvents.SaveResource, (data) => this.handleSaveResource(data));
         this.subscribeToEvent(EditorEvents.SaveResource, (data) => this.handleSaveResource(data));
         this.subscribeToEvent(EditorEvents.SaveAllResources, (data) => this.handleSaveAllResources(data));
         this.subscribeToEvent(EditorEvents.SaveAllResources, (data) => this.handleSaveAllResources(data));
         this.subscribeToEvent(EditorEvents.EditorResourceClose, (ev: EditorEvents.EditorCloseResourceEvent) => this.handleCloseResource(ev));
         this.subscribeToEvent(EditorEvents.EditorResourceClose, (ev: EditorEvents.EditorCloseResourceEvent) => this.handleCloseResource(ev));
+        this.subscribeToEvent(EditorEvents.RenameResourceNotification, (ev: EditorEvents.RenameResourceEvent) => this.handleRenameResource(ev));
+        this.subscribeToEvent(EditorEvents.DeleteResourceNotification, (data) => this.handleDeleteResource(data));
 
 
         this.subscribeToEvent(UIEvents.ResourceEditorChanged, (data) => this.handleResourceEditorChanged(data));
         this.subscribeToEvent(UIEvents.ResourceEditorChanged, (data) => this.handleResourceEditorChanged(data));
 
 

+ 1 - 1
Script/AtomicEditor/ui/frames/inspector/InspectorFrame.ts

@@ -54,7 +54,7 @@ class InspectorFrame extends ScriptWidget {
         var container = this.getWidget("inspectorcontainer");
         var container = this.getWidget("inspectorcontainer");
 
 
         this.subscribeToEvent(EditorEvents.EditResource, (data) => this.handleEditResource(data));
         this.subscribeToEvent(EditorEvents.EditResource, (data) => this.handleEditResource(data));
-        this.subscribeToEvent("ProjectUnloaded", (data) => this.handleProjectUnloaded(data));
+        this.subscribeToEvent(EditorEvents.ProjectUnloadedNotification, (data) => this.handleProjectUnloaded(data));
 
 
         this.subscribeToEvent(EditorEvents.ActiveSceneEditorChange, (data) => this.handleActiveSceneEditorChanged(data));
         this.subscribeToEvent(EditorEvents.ActiveSceneEditorChange, (data) => this.handleActiveSceneEditorChanged(data));
 
 

+ 1 - 1
Script/AtomicEditor/ui/modal/CreateProject.ts

@@ -24,7 +24,7 @@ import EditorEvents = require("../../editor/EditorEvents");
 import EditorUI = require("../EditorUI");
 import EditorUI = require("../EditorUI");
 import ModalWindow = require("./ModalWindow");
 import ModalWindow = require("./ModalWindow");
 
 
-import ProjectTemplates = require("../resources/ProjectTemplates");
+import ProjectTemplates = require("../../resources/ProjectTemplates");
 
 
 class CreateProject extends ModalWindow {
 class CreateProject extends ModalWindow {
 
 

+ 8 - 4
Script/AtomicEditor/ui/modal/UIResourceOps.ts

@@ -376,12 +376,16 @@ export class RenameAsset extends ModalWindow {
                 this.hide();
                 this.hide();
 
 
                 if (this.asset.name != this.nameEdit.text) {
                 if (this.asset.name != this.nameEdit.text) {
-                    let eventData = {
-                        path: this.asset.path,
-                        newPath: this.nameEdit.text,
+                    let oldPath = this.asset.path;
+                    this.asset.rename(this.nameEdit.text);
+
+                    let eventData: EditorEvents.RenameResourceEvent = {
+                        path: oldPath,
+                        newPath: this.asset.path,
+                        newName: this.nameEdit.text,
                         asset: this.asset
                         asset: this.asset
                     };
                     };
-                    this.asset.rename(this.nameEdit.text);
+
                     this.sendEvent(EditorEvents.RenameResourceNotification, eventData);
                     this.sendEvent(EditorEvents.RenameResourceNotification, eventData);
                 }
                 }
 
 

+ 2 - 2
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/TypescriptLanguageExtension.ts

@@ -219,7 +219,7 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
      */
      */
     delete(ev: Editor.EditorEvents.DeleteResourceEvent) {
     delete(ev: Editor.EditorEvents.DeleteResourceEvent) {
         if (this.isValidFiletype(ev.path)) {
         if (this.isValidFiletype(ev.path)) {
-            console.log(`${this.name}: received a delete resource event`);
+            console.log(`${this.name}: received a delete resource event for ${ev.path}`);
 
 
             // notify the typescript language service that the file has been deleted
             // notify the typescript language service that the file has been deleted
             const message: WorkerProcessTypes.DeleteMessageData = {
             const message: WorkerProcessTypes.DeleteMessageData = {
@@ -237,7 +237,7 @@ export default class TypescriptLanguageExtension implements Editor.ClientExtensi
      */
      */
     rename(ev: Editor.EditorEvents.RenameResourceEvent) {
     rename(ev: Editor.EditorEvents.RenameResourceEvent) {
         if (this.isValidFiletype(ev.path)) {
         if (this.isValidFiletype(ev.path)) {
-            console.log(`${this.name}: received a rename resource event`);
+            console.log(`${this.name}: received a rename resource event for ${ev.path} -> ${ev.newPath}`);
 
 
             // notify the typescript language service that the file has been renamed
             // notify the typescript language service that the file has been renamed
             const message: WorkerProcessTypes.RenameMessageData = {
             const message: WorkerProcessTypes.RenameMessageData = {

+ 10 - 0
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/TypescriptLanguageService.ts

@@ -140,6 +140,13 @@ export class TypescriptLanguageService {
             this.versionMap[filename].version.toString());
             this.versionMap[filename].version.toString());
     }
     }
 
 
+    /**
+     * Returns the list of project files
+     * @return {string[]}
+     */
+    getProjectFiles(): string[] {
+        return this.projectFiles;
+    }
     /**
     /**
      * 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
@@ -243,6 +250,7 @@ export class TypescriptLanguageService {
         }
         }
         let idx = this.projectFiles.indexOf(filepath);
         let idx = this.projectFiles.indexOf(filepath);
         if (idx > -1) {
         if (idx > -1) {
+            console.log(`delete project file from ${filepath}`);
             this.projectFiles.splice(idx, 1);
             this.projectFiles.splice(idx, 1);
         }
         }
     }
     }
@@ -255,11 +263,13 @@ export class TypescriptLanguageService {
     renameProjectFile(filepath: string, newpath: string): void {
     renameProjectFile(filepath: string, newpath: string): void {
         let oldFile = this.versionMap[filepath];
         let oldFile = this.versionMap[filepath];
         if (oldFile) {
         if (oldFile) {
+            console.log(`Rename project file from ${filepath} to ${newpath}`);
             delete this.versionMap[filepath];
             delete this.versionMap[filepath];
             this.versionMap[newpath] = oldFile;
             this.versionMap[newpath] = oldFile;
         }
         }
         let idx = this.projectFiles.indexOf(filepath);
         let idx = this.projectFiles.indexOf(filepath);
         if (idx > -1) {
         if (idx > -1) {
+            console.log(`Update project files array from ${filepath} to ${newpath}`)
             this.projectFiles[idx] = newpath;
             this.projectFiles[idx] = newpath;
         }
         }
     }
     }

+ 28 - 19
Script/AtomicWebViewEditor/clientExtensions/languageExtensions/typescript/workerprocess/TypescriptLanguageServiceWebWorker.ts

@@ -185,30 +185,39 @@ export default class TypescriptLanguageServiceWebWorker {
      * @return {Promise}
      * @return {Promise}
      */
      */
     private loadProjectFiles() {
     private loadProjectFiles() {
-        if (!this.projectLoaded) {
-            return getFileResource("resources/tsconfig.atomic").then((jsonTsConfig: string) => {
-                let promises: PromiseLike<void>[] = [];
-                let tsConfig: TSConfigFile = JSON.parse(jsonTsConfig);
-
-                if (tsConfig.compilerOptions) {
-                    this.languageService.compilerOptions = tsConfig.compilerOptions;
-                };
+        // Let's query the backend and get a list of the current files
+        // and delete any that may be been removed and sync up
+        return getFileResource("resources/tsconfig.atomic").then((jsonTsConfig: string) => {
+            let promises: PromiseLike<void>[] = [];
+            let tsConfig: TSConfigFile = JSON.parse(jsonTsConfig);
+
+            if (tsConfig.compilerOptions) {
+                this.languageService.compilerOptions = tsConfig.compilerOptions;
+            };
+
+            let existingFiles = this.languageService.getProjectFiles();
+
+            // see if anything was deleted
+            existingFiles.forEach((f) => {
+                if (tsConfig.files.indexOf(f) == -1) {
+                    this.languageService.deleteProjectFile(f);
+                }
+            });
 
 
-                tsConfig.files.forEach((f) => {
+            // load up any new files that may have been added
+            tsConfig.files.forEach((f) => {
+                if (existingFiles.indexOf(f) == -1) {
                     promises.push(getFileResource(f).then((code: string) => {
                     promises.push(getFileResource(f).then((code: string) => {
                         this.languageService.addProjectFile(f, code);
                         this.languageService.addProjectFile(f, code);
                     }));
                     }));
-                });
-                return Promise.all(promises);
-            }).then(() => {
-                // Let's seed the compiler state
-                // this.languageService.compile([this.filename]);
-                this.projectLoaded = true;
+                }
             });
             });
-        } else {
-            // just return a resolved promise.. we are done
-            return Promise.resolve();
-        }
+            return Promise.all(promises);
+        }).then(() => {
+            // Let's seed the compiler state
+            // this.languageService.compile([this.filename]);
+            this.projectLoaded = true;
+        });
     }
     }
 
 
     /**
     /**

+ 0 - 1
Script/AtomicWebViewEditor/interop.ts

@@ -175,7 +175,6 @@ export default class HostInteropType {
      */
      */
     resourceRenamed(path: string, newPath: string) {
     resourceRenamed(path: string, newPath: string) {
         editorCommands.resourceRenamed(path, newPath);
         editorCommands.resourceRenamed(path, newPath);
-
     }
     }
 
 
     /**
     /**

+ 1 - 1
Script/AtomicWebViewEditor/typings/WindowExt.d.ts

@@ -14,6 +14,6 @@ interface Window {
     HOST_saveCode: () => void;
     HOST_saveCode: () => void;
 
 
     HOST_projectUnloaded: () => void;
     HOST_projectUnloaded: () => void;
-    HOST_resourceRenamed: (path:string, newPath:string) => void;
+    HOST_resourceRenamed: (path: string, newPath: string) => void;
     HOST_resourceDeleted: (path: string) => void;
     HOST_resourceDeleted: (path: string) => void;
 }
 }

+ 18 - 1
Script/TypeScript/EditorWork.d.ts

@@ -107,9 +107,26 @@ declare module Editor.EditorEvents {
      */
      */
     export interface RenameResourceEvent {
     export interface RenameResourceEvent {
 
 
-        // The full path to the resource to edit
+        /**
+         * Original path of the resource
+         * @type {string}
+         */
         path: string;
         path: string;
+
+        /**
+         * New path of the resource
+         * @type {string}
+         */
         newPath: string;
         newPath: string;
+
+        /**
+         * New base name of the resource (no path or extension)
+         * @type {string}
+         */
+        newName?: string;
+
+        // the asset being changed
+        asset?: ToolCore.Asset;
     }
     }
 
 
     export interface SceneEditStateChangeEvent {
     export interface SceneEditStateChangeEvent {

+ 1 - 1
Submodules/CEF

@@ -1 +1 @@
-Subproject commit a74fdafc2f42f4349d777e1a1fb20f63e848da23
+Subproject commit 0193bbffe0a032649014cf032bcea08ec58eed7f