2
0
Эх сурвалжийг харах

review and fixed script caching

Nicolas Cannasse 8 сар өмнө
parent
commit
008cdc9971

+ 7 - 2
hide/comp/DomkitEditor.hx

@@ -60,8 +60,6 @@ class DomkitChecker extends ScriptEditor.ScriptChecker {
 
 	public function new(config) {
 		super(config,"domkit");
-		t_string = checker.types.resolve("String");
-
 		parsers = [new h2d.domkit.BaseComponents.CustomParser()];
 		var dcfg : Array<String> = config.get("domkit.parsers");
 		if( dcfg != null ) {
@@ -74,7 +72,14 @@ class DomkitChecker extends ScriptEditor.ScriptChecker {
 				parsers.push(std.Type.createInstance(cl,[]));
 			}
 		}
+	}
+
+	override function initTypes() {
+		if( !super.initTypes() )
+			return false;
+		t_string = checker.types.resolve("String");
 		initComponents();
+		return true;
 	}
 
 	public function checkDML( dmlCode : String, filePath : String, position = 0 ) {

+ 89 - 48
hide/comp/ScriptEditor.hx

@@ -14,9 +14,15 @@ class ScriptCache {
 
 	var content : Map<String,Bool> = [];
 	var configSign : String;
+	public var files : Array<String>;
+	public var apiHash : String;
+	public var types : hscript.Checker.CheckerTypes;
 
-	public function new(configSign:String) {
-		this.configSign = configSign;
+	public function new() {
+	}
+
+	public function loadConfig( sign : String ) {
+		this.configSign = sign;
 		var key = hide.Ide.inst.localStorage.getItem("script_cache_key");
 		if( key == configSign ) {
 			var values = hide.Ide.inst.localStorage.getItem("script_cache_val").split(";");
@@ -25,11 +31,28 @@ class ScriptCache {
 		}
 	}
 
-	public function get( hash : String ) {
+	public function loadFiles( files : Array<String> ) {
+		var hash = getFilesHash(files);
+		if( hash == apiHash ) return;
+		apiHash = hash;
+		this.files = files;
+		types = new hscript.Checker.CheckerTypes();
+		if( files != null ) {
+			var ide = hide.Ide.inst;
+			for( f in files ) {
+				var path = ide.getPath(f);
+				var content = try sys.io.File.getContent(path) catch( e : Dynamic ) { @:privateAccess ScriptChecker.error(""+e); continue; };
+				types.addXmlApi(Xml.parse(content).firstElement());
+				ide.fileWatcher.register(f, function() { onApiFileChange(); loadFiles(files); });
+			}
+		}
+	}
+
+	public function getResult( hash : String ) {
 		return content.get(hash);
 	}
 
-	public function set( hash : String, b : Bool ) {
+	public function setResult( hash : String, b : Bool ) {
 		if( content.get(hash) == b ) return;
 		content.set(hash, b);
 		var all = [];
@@ -50,46 +73,77 @@ class ScriptCache {
 		return haxe.crypto.Md5.encode(str);
 	}
 
+	static function getFilesHash( files : Array<String> ) {
+		var ide = hide.Ide.inst;
+		var hashes = [];
+		for( f in files ) {
+			var path = ide.getPath(f);
+			hashes.push(path+":"+sys.FileSystem.stat(path).mtime.getTime());
+		}
+		return hashString(hashes.join(","));
+	}
+
+	static function onApiFileChange() {
+		CONFIG_HASH = null;
+		LAST_API = null;
+		LAST_FILES = null;
+		LAST_API_FILES = null;
+		LAST_API_TYPES = null;
+	}
+
 	public static function getCachedResult( config : hide.Config, documentName : String, constants : Map<String,Dynamic>, code : String ) : Bool {
 		var api = config.get("script.api");
 		var apiFiles : Array<String> = config.get("script.api.files");
 		if( api != LAST_API || apiFiles != LAST_FILES || CHECK_CACHE == null ) {
 			LAST_API = api;
 			LAST_FILES = apiFiles;
-			var hashes = [];
-			var ide = hide.Ide.inst;
-			for( f in apiFiles ) {
-				var path = ide.getPath(f);
-				hashes.push(path+":"+sys.FileSystem.stat(path).mtime.getTime());
-			}
-			hashes.push(haxe.Json.stringify(api));
-			var hash = hashString(hashes.join(","));
+			var hash = hashString(getFilesHash(apiFiles) + haxe.Json.stringify(api));
 			if( hash != CONFIG_HASH ) {
 				// CDB has a single configuration
 				CONFIG_HASH = hash;
-				CHECK_CACHE = new ScriptCache(hash);
+				CHECK_CACHE = new ScriptCache();
+				CHECK_CACHE.loadConfig(hash);
 			}
 		}
 		var cache = CHECK_CACHE;
 		var signature = hashString(code+":"+documentName+":"+haxe.Json.stringify(constants));
-		var error : Null<Bool> = cache.get(signature);
+		var error : Null<Bool> = cache.getResult(signature);
 		if( error == null ) {
 			var chk = new ScriptChecker(config, documentName, constants);
 			error = chk.check(code) != null;
-			cache.set(signature, error);
+			cache.setResult(signature, error);
 		}
 		return error;
 	}
 
+	static var TYPES_SAVE = new Map();
+	static var LAST_API_FILES = null;
+	static var LAST_API_TYPES = null;
+
+	public static function loadApiFiles( config : hide.Config ) {
+		var files = config.get("script.api.files");
+		if( files != LAST_API_FILES || LAST_API_TYPES == null ) {
+			var key = files.join(";");
+			var types = TYPES_SAVE.get(key);
+			if( types == null ) {
+				types = new ScriptCache();
+				types.loadFiles(files);
+				TYPES_SAVE.set(key,types);
+			}
+			LAST_API_FILES = files;
+			LAST_API_TYPES = types;
+		}
+		return LAST_API_TYPES;
+	}
+
 }
 
 class ScriptChecker {
 
-	static var TYPES_SAVE = new Map();
 	static var ERROR_SAVE = new Map();
 	static var TYPE_CHECK_HOOKS : Array<ScriptChecker->Void> = [];
 	var ide : hide.Ide;
-	var apiFiles : Array<String>;
+	var api : ScriptCache;
 	var checkEvents : Bool;
 	public var config : hide.Config;
 	public var documentName : String;
@@ -97,35 +151,26 @@ class ScriptChecker {
 	public var evalTo : String;
 	public var checker(default,null) : hscript.Checker;
 	var initDone = false;
+	var apiHash : String;
 
 	public function new( config : hide.Config, documentName : String, ?constants : Map<String,Dynamic> ) {
 		this.config = config;
 		this.documentName = documentName;
 		this.constants = constants == null ? new Map() : constants;
 		ide = hide.Ide.inst;
-		apiFiles = config.get("script.api.files");
-		reload();
+		api = ScriptCache.loadApiFiles(config);
+		initTypes();
 	}
 
-	public function reload() {
+	function initTypes() {
+		if( apiHash == api.apiHash )
+			return false;
+		apiHash = api.apiHash;
 		checker = new hscript.Checker();
 		checker.allowAsync = true;
+		checker.types = api.types;
 		initDone = false;
-
-		if( apiFiles != null && apiFiles.length >= 0 ) {
-			var types = TYPES_SAVE.get(apiFiles.join(";"));
-			if( types == null ) {
-				types = new hscript.Checker.CheckerTypes();
-				for( f in apiFiles ) {
-					var path = ide.getPath(f);
-					var content = try sys.io.File.getContent(path) catch( e : Dynamic ) { error(""+e); continue; };
-					types.addXmlApi(Xml.parse(content).firstElement());
-					ide.fileWatcher.register(f, reloadApi);
-				}
-				TYPES_SAVE.set(apiFiles.join(";"), types);
-			}
-			checker.types = types;
-		}
+		return true;
 	}
 
 	function resolveApis( path : String ) {
@@ -160,6 +205,7 @@ class ScriptChecker {
 	}
 
 	function init() {
+		initTypes();
 		if( initDone ) return;
 		initDone = true;
 
@@ -203,7 +249,7 @@ class ScriptChecker {
 					}
 				}
 				if( t == null ) {
-					error('Global type $tname not found in $apiFiles ($f)');
+					error('Global type $tname not found in ${this.api.files} ($f)');
 					continue;
 				}
 				if( isClass ) {
@@ -277,10 +323,10 @@ class ScriptChecker {
 		return fl;
 	}
 
-	function error( msg : String ) {
+	static function error( msg : String ) {
 		if( !ERROR_SAVE.exists(msg) ) {
 			ERROR_SAVE.set(msg,true);
-			ide.error(msg);
+			hide.Ide.inst.error(msg);
 		}
 	}
 
@@ -378,6 +424,9 @@ class ScriptChecker {
 		try {
 			var expr = parser.parseString(script, "");
 
+			if( checkTypes )
+				init();
+
 			if( checkEvents ) {
 				function checkRec(e:hscript.Expr) {
 					switch( e.e ) {
@@ -392,7 +441,6 @@ class ScriptChecker {
 			}
 
 			if( checkTypes ) {
-				init();
 				var et = checker.check(expr);
 				if( evalTo != null ) {
 					var t = checker.types.resolve(evalTo);
@@ -409,10 +457,6 @@ class ScriptChecker {
 		}
 	}
 
-	public static function reloadApi() {
-		TYPES_SAVE = new Map();
-	}
-
 }
 
 #if !hl
@@ -427,13 +471,10 @@ class ScriptEditor extends CodeEditor {
 			checker = new ScriptChecker(new hide.Config(),"");
 			checkTypes = false;
 		} else {
-			var files = @:privateAccess checker.apiFiles;
+			var files = @:privateAccess checker.api.files;
 			if( files != null ) {
 				for( f in files )
-					ide.fileWatcher.register(f, function() {
-						ScriptChecker.reloadApi();
-						haxe.Timer.delay(function() { try checker.reload() catch( e : Dynamic ) {}; doCheckScript(); }, 100);
-					}, root);
+					ide.fileWatcher.register(f, function() haxe.Timer.delay(doCheckScript,100), root);
 			}
 		}
 		this.checker = checker;