private static void ConstructCache(Script scriptToCache, bool isBackgroundThread) { string originalText = scriptToCache.Text; ScriptAutoCompleteData newCache = new ScriptAutoCompleteData(); List<ScriptVariable> variables = newCache.Variables; List<ScriptFunction> functions = newCache.Functions; List<ScriptDefine> defines = newCache.Defines; List<ScriptEnum> enums = newCache.Enums; List<ScriptStruct> structs = newCache.Structs; variables.Clear(); functions.Clear(); defines.Clear(); enums.Clear(); structs.Clear(); FastString script = originalText; AutoCompleteParserState state = new AutoCompleteParserState(); ScriptFunction lastFunction = null; int counter = 0; while (script.Length > 0) { if (isBackgroundThread) { counter++; if (counter % 20 == 0) { Thread.Sleep(2); } } SkipWhitespace(ref script); state.CurrentScriptCharacterIndex = originalText.Length - script.Length; if (script.Length == 0) { break; } if (script.StartsWith("//")) { FastString scriptAtComment = script; GoToNextLine(ref script); if (scriptAtComment.StartsWith("///")) { FastString commentText = scriptAtComment.Substring(3, (scriptAtComment.Length - script.Length) - 4); state.PreviousComment = commentText.ToString().Trim(); } continue; } if (script.StartsWith("/*")) { int endOfComment = script.IndexOf("*/"); if (endOfComment < 0) { break; } script = script.Substring(endOfComment + 2); continue; } if (script.StartsWith("#")) { ProcessPreProcessorDirective(defines, ref script, state); continue; } if (script.StartsWith("{")) { if (state.WordBeforeLast == "enum") { state.InsideEnumDefinition = new ScriptEnum(state.LastWord, state.InsideIfDefBlock, state.InsideIfNDefBlock); } else if (state.WordBeforeLast == "extends") { // inherited struct foreach (ScriptStruct baseStruct in structs) { if (baseStruct.Name == state.LastWord) { state.InsideStructDefinition = CreateInheritedStruct(baseStruct, state); functions = state.InsideStructDefinition.Functions; variables = state.InsideStructDefinition.Variables; break; } } } else if (state.WordBeforeLast == "struct") { state.InsideStructDefinition = new ScriptStruct(state.LastWord, state.InsideIfDefBlock, state.InsideIfNDefBlock, state.CurrentScriptCharacterIndex); functions = state.InsideStructDefinition.Functions; variables = state.InsideStructDefinition.Variables; } else { state.ClearPreviousWords(); SkipUntilMatchingClosingBrace(ref script); if ((lastFunction != null) && (lastFunction.EndsAtCharacterIndex == 0)) { lastFunction.EndsAtCharacterIndex = originalText.Length - script.Length; } continue; } } string thisWord = GetNextWord(ref script); if (thisWord == "(") { List<ScriptFunction> functionList = functions; bool isExtenderMethod = AdjustFunctionListForExtenderFunction(structs, ref functionList, ref script); if (AddFunctionDeclaration(functionList, ref script, thisWord, state, isExtenderMethod)) { lastFunction = functionList[functionList.Count - 1]; } state.ClearPreviousWords(); } else if ((thisWord == "[") && (PeekNextWord(script) == "]")) { GetNextWord(ref script); state.DynamicArrayDefinition = true; state.AddNextWord("[]"); } else if ((thisWord == "=") || (thisWord == ";") || (thisWord == ",") || (thisWord == "[")) { if (state.InsideEnumDefinition != null) { AddEnumValue(state.InsideEnumDefinition, script, state.LastWord); if (thisWord == "=") { // skip whatever the value of the enum is GetNextWord(ref script); } } else { AddVariableDeclaration(variables, ref script, thisWord, state); if (thisWord == "=") { while ((thisWord != ";") && (thisWord != ",") && (script.Length > 0)) { thisWord = GetNextWord(ref script); } } if (thisWord == ",") { // eg. "int x,y"; ensure "y" gets recorded next time round state.UndoLastWord(); continue; } if (thisWord == "[") { // eg. "int a[10], b[10], c[10];" SkipWhitespace(ref script); if (script.StartsWith(",")) { GetNextWord(ref script); state.UndoLastWord(); continue; } } } state.ClearPreviousWords(); state.DynamicArrayDefinition = false; } else if ((thisWord == "}") && (state.InsideEnumDefinition != null)) { // add the last value (unless it's an empty enum) if (state.LastWord != "{") { AddEnumValue(state.InsideEnumDefinition, script, state.LastWord); } enums.Add(state.InsideEnumDefinition); state.InsideEnumDefinition = null; state.ClearPreviousWords(); } else if ((thisWord == "}") && (state.InsideStructDefinition != null)) { structs.Add(state.InsideStructDefinition); functions = newCache.Functions; variables = newCache.Variables; state.InsideStructDefinition = null; state.ClearPreviousWords(); } else { state.AddNextWord(thisWord); } } scriptToCache.AutoCompleteData.CopyFrom(newCache); scriptToCache.AutoCompleteData.Populated = true; }
private static void ConstructCache(Script scriptToCache, bool isBackgroundThread) { string originalText = scriptToCache.Text; ScriptAutoCompleteData newCache = new ScriptAutoCompleteData(); List <ScriptVariable> variables = newCache.Variables; List <ScriptFunction> functions = newCache.Functions; List <ScriptDefine> defines = newCache.Defines; List <ScriptEnum> enums = newCache.Enums; List <ScriptStruct> structs = newCache.Structs; variables.Clear(); functions.Clear(); defines.Clear(); enums.Clear(); structs.Clear(); FastString script = originalText; AutoCompleteParserState state = new AutoCompleteParserState(); ScriptFunction lastFunction = null; int counter = 0; while (script.Length > 0) { if (isBackgroundThread) { counter++; if (counter % 20 == 0) { Thread.Sleep(2); } } SkipWhitespace(ref script); state.CurrentScriptCharacterIndex = originalText.Length - script.Length; if (script.Length == 0) { break; } if (script.StartsWith("//")) { FastString scriptAtComment = script; GoToNextLine(ref script); if (scriptAtComment.StartsWith("///")) { FastString commentText = scriptAtComment.Substring(3, (scriptAtComment.Length - script.Length) - 4); state.PreviousComment = commentText.ToString().Trim(); } continue; } if (script.StartsWith("/*")) { int endOfComment = script.IndexOf("*/"); if (endOfComment < 0) { break; } script = script.Substring(endOfComment + 2); continue; } if (script.StartsWith("#")) { ProcessPreProcessorDirective(defines, ref script, state); continue; } if (script.StartsWith("{")) { if (state.WordBeforeLast == "enum") { state.InsideEnumDefinition = new ScriptEnum(state.LastWord, state.InsideIfDefBlock, state.InsideIfNDefBlock); } else if (state.WordBeforeLast == "extends") { // inherited struct foreach (ScriptStruct baseStruct in structs) { if (baseStruct.Name == state.LastWord) { state.InsideStructDefinition = CreateInheritedStruct(baseStruct, state); functions = state.InsideStructDefinition.Functions; variables = state.InsideStructDefinition.Variables; break; } } } else if (state.WordBeforeLast == "struct") { state.InsideStructDefinition = new ScriptStruct(state.LastWord, state.InsideIfDefBlock, state.InsideIfNDefBlock, state.CurrentScriptCharacterIndex); functions = state.InsideStructDefinition.Functions; variables = state.InsideStructDefinition.Variables; } else { state.ClearPreviousWords(); SkipUntilMatchingClosingBrace(ref script); if ((lastFunction != null) && (lastFunction.EndsAtCharacterIndex == 0)) { lastFunction.EndsAtCharacterIndex = originalText.Length - script.Length; } continue; } } string thisWord = GetNextWord(ref script); if (thisWord == "(") { List <ScriptFunction> functionList = functions; bool isExtenderMethod = AdjustFunctionListForExtenderFunction(structs, ref functionList, ref script); if (AddFunctionDeclaration(functionList, ref script, thisWord, state, isExtenderMethod)) { lastFunction = functionList[functionList.Count - 1]; } state.ClearPreviousWords(); } else if ((thisWord == "[") && (PeekNextWord(script) == "]")) { GetNextWord(ref script); state.DynamicArrayDefinition = true; state.AddNextWord("[]"); } else if ((thisWord == "=") || (thisWord == ";") || (thisWord == ",") || (thisWord == "[")) { if (state.InsideEnumDefinition != null) { AddEnumValue(state.InsideEnumDefinition, script, state.LastWord); if (thisWord == "=") { // skip whatever the value of the enum is GetNextWord(ref script); } } else { AddVariableDeclaration(variables, ref script, thisWord, state); if (thisWord == "=") { while ((thisWord != ";") && (thisWord != ",") && (script.Length > 0)) { thisWord = GetNextWord(ref script); } } if (thisWord == ",") { // eg. "int x,y"; ensure "y" gets recorded next time round state.UndoLastWord(); continue; } if (thisWord == "[") { // eg. "int a[10], b[10], c[10];" SkipWhitespace(ref script); if (script.StartsWith(",")) { GetNextWord(ref script); state.UndoLastWord(); continue; } } } state.ClearPreviousWords(); state.DynamicArrayDefinition = false; } else if ((thisWord == "}") && (state.InsideEnumDefinition != null)) { // add the last value (unless it's an empty enum) if (state.LastWord != "{") { AddEnumValue(state.InsideEnumDefinition, script, state.LastWord); } enums.Add(state.InsideEnumDefinition); state.InsideEnumDefinition = null; state.ClearPreviousWords(); } else if ((thisWord == "}") && (state.InsideStructDefinition != null)) { structs.Add(state.InsideStructDefinition); functions = newCache.Functions; variables = newCache.Variables; state.InsideStructDefinition = null; state.ClearPreviousWords(); } else { state.AddNextWord(thisWord); } } scriptToCache.AutoCompleteData.CopyFrom(newCache); scriptToCache.AutoCompleteData.Populated = true; }
public static void ConstructCache(Script scriptToCache, IEnumerable <Script> importScripts) { string originalText = scriptToCache.Text; ScriptAutoCompleteData newCache = new ScriptAutoCompleteData(); List <ScriptVariable> variables = newCache.Variables; List <ScriptFunction> functions = newCache.Functions; List <ScriptDefine> defines = newCache.Defines; List <ScriptEnum> enums = newCache.Enums; List <ScriptStruct> structs = newCache.Structs; variables.Clear(); functions.Clear(); defines.Clear(); enums.Clear(); structs.Clear(); FastString script = originalText; AutoCompleteParserState state = new AutoCompleteParserState(); ScriptFunction lastFunction = null; // Struct lookup will have both local and imported types List <ScriptStruct> structsLookup = new List <ScriptStruct>(); if (importScripts != null) { foreach (var import in importScripts) { structsLookup.AddRange(import.AutoCompleteData.Structs); } } while (script.Length > 0) { SkipWhitespace(ref script); state.CurrentScriptCharacterIndex = originalText.Length - script.Length; if (script.Length == 0) { break; } if (script.StartsWith("//")) { FastString scriptAtComment = script; GoToNextLine(ref script); if (scriptAtComment.StartsWith("///")) { FastString commentText = scriptAtComment.Substring(3, (scriptAtComment.Length - script.Length) - 3); state.PreviousComment = commentText.ToString().Trim(); } continue; } if (script.StartsWith("/*")) { int endOfComment = script.IndexOf("*/"); if (endOfComment < 0) { break; } script = script.Substring(endOfComment + 2); continue; } if (script.StartsWith("#")) { ProcessPreProcessorDirective(defines, ref script, state); continue; } if (script.StartsWith("{")) { if (state.WordBeforeLast == "enum") { state.InsideEnumDefinition = new ScriptEnum(state.LastWord, state.InsideIfDefBlock, state.InsideIfNDefBlock); } else if (state.WordBeforeLast == "extends") { // inherited struct foreach (ScriptStruct baseStruct in structsLookup) { if (baseStruct.Name == state.LastWord) { state.InsideStructDefinition = CreateInheritedStruct(baseStruct, state); functions = state.InsideStructDefinition.Functions; variables = state.InsideStructDefinition.Variables; break; } } } else if (state.WordBeforeLast == "struct") { state.InsideStructDefinition = new ScriptStruct(state.LastWord, state.InsideIfDefBlock, state.InsideIfNDefBlock, state.CurrentScriptCharacterIndex); functions = state.InsideStructDefinition.Functions; variables = state.InsideStructDefinition.Variables; } else { state.ClearPreviousWords(); SkipUntilMatchingClosingBrace(ref script); if ((lastFunction != null) && (lastFunction.EndsAtCharacterIndex == 0)) { lastFunction.EndsAtCharacterIndex = originalText.Length - script.Length; } continue; } } string thisWord = GetNextWord(ref script); if (thisWord == "(") { List <ScriptFunction> functionList = functions; bool isStaticExtender = script.StartsWith("static "); bool isExtenderMethod = isStaticExtender || script.StartsWith("this "); if (isExtenderMethod) { ScriptStruct newStruct = null; // NOTE: for extenders we DO NOT look up the global struct list; // the reason is a bit complicated, but in a nutshell: // we need to have a list of extender functions bound to the // struct defs in the *local* script's autocomplete cache, not the // imported script's cache. The struct defs may be duplicated this // way, but that's mostly fine, as these may be merged together; // e.g. see ScintillaWrapper.GetAllStructsWithMatchingName(). AdjustFunctionListForExtenderFunction(structs, ref functionList, ref newStruct, ref script); if (newStruct != null) { structs.Add(newStruct); structsLookup.Add(newStruct); } } if (AddFunctionDeclaration(functionList, ref script, thisWord, state, isExtenderMethod, isStaticExtender, isStaticExtender)) { lastFunction = functionList[functionList.Count - 1]; } state.ClearPreviousWords(); } else if ((thisWord == "[") && (PeekNextWord(script) == "]")) { GetNextWord(ref script); state.DynamicArrayDefinition = true; state.AddNextWord("[]"); } else if ((thisWord == "=") || (thisWord == ";") || (thisWord == ",") || (thisWord == "[")) { if (state.InsideEnumDefinition != null) { AddEnumValue(state.InsideEnumDefinition, script, state.LastWord); if (thisWord == "=") { // skip whatever the value of the enum is GetNextWord(ref script); } } else { AddVariableDeclaration(variables, ref script, thisWord, state); if (thisWord == "=") { while ((thisWord != ";") && (thisWord != ",") && (script.Length > 0)) { thisWord = GetNextWord(ref script); } } if (thisWord == ",") { // eg. "int x,y"; ensure "y" gets recorded next time round state.UndoLastWord(); continue; } if (thisWord == "[") { // eg. "int a[10], b[10], c[10];" SkipWhitespace(ref script); if (script.StartsWith(",")) { GetNextWord(ref script); state.UndoLastWord(); continue; } } } state.ClearPreviousWords(); state.DynamicArrayDefinition = false; } else if ((thisWord == "}") && (state.InsideEnumDefinition != null)) { // add the last value (unless it's an empty enum) if (state.LastWord != "{") { AddEnumValue(state.InsideEnumDefinition, script, state.LastWord); } enums.Add(state.InsideEnumDefinition); state.InsideEnumDefinition = null; state.ClearPreviousWords(); } else if ((thisWord == "}") && (state.InsideStructDefinition != null)) { structs.Add(state.InsideStructDefinition); structsLookup.Add(state.InsideStructDefinition); // Restore struct member references to global script ones functions = newCache.Functions; variables = newCache.Variables; state.InsideStructDefinition = null; state.ClearPreviousWords(); } else { state.AddNextWord(thisWord); } } scriptToCache.AutoCompleteData.CopyFrom(newCache); scriptToCache.AutoCompleteData.Populated = true; }