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 isStaticExtender = script.StartsWith("static ");
bool isExtenderMethod = isStaticExtender || script.StartsWith("this ");
if(isExtenderMethod)
AdjustFunctionListForExtenderFunction(structs, ref functionList, ref script);
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);
functions = newCache.Functions;
variables = newCache.Variables;
state.InsideStructDefinition = null;
state.ClearPreviousWords();
}
else
{
state.AddNextWord(thisWord);
}
}
scriptToCache.AutoCompleteData.CopyFrom(newCache);
scriptToCache.AutoCompleteData.Populated = true;
}