/External/Plugins/ASCompletion/Model/ASFileParser.cs
C# | 1538 lines | 1265 code | 122 blank | 151 comment | 668 complexity | 3c766f883597272b824b948e4dda89d9 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.0, BSD-2-Clause
Large files files are truncated, but you can click here to view the full file
- /*
- *
- * User: Philippe Elsass
- * Date: 18/03/2006
- * Time: 19:03
- */
-
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text.RegularExpressions;
- using ASCompletion.Completion;
- using ASCompletion.Context;
-
- namespace ASCompletion.Model
- {
-
- #region Token class
- class Token
- {
- public int Position;
- public int Line;
- public string Text;
-
- public Token()
- {
- }
-
- public Token(Token copy)
- {
- Text = copy.Text;
- Line = copy.Line;
- Position = copy.Position;
- }
-
- override public string ToString()
- {
- return Text;
- }
- }
- #endregion
-
- #region TypeDefinitionKind enum
- /// <summary>
- /// Contributor: i.o.
- /// </summary>
- public enum TypeDefinitionKind : uint
- {
- Null = 0,
- Simple = 1,
- TypedArray = 2,
- TypedCallback = 3,
- TypedObject = 4
- }
- //
- #endregion
-
- #region TypeCommentUtils class
- /// <summary>
- /// Contributor: i.o.
- /// </summary>
- public class TypeCommentUtils
- {
- //---------------------
- // FIELDS
- //---------------------
-
- public static string ObjectType = "Object"; // will differ in haxe
- private static Random random = new Random(123456);
-
-
- //---------------------
- // PUBLIC METHODS
- //---------------------
-
- /// <summary>
- /// Type-comment parsing into model (source and destination)
- /// </summary>
- public static TypeDefinitionKind Parse(string comment, MemberModel model)
- {
- return Parse(comment, model, false);
- }
- public static TypeDefinitionKind Parse(string comment, MemberModel model, bool detectKindOnly)
- {
- if (model != null && comment != null && comment != "")
- {
- switch (model.Type)
- {
- case "Array":
- return ParseTypedArray(comment, model, detectKindOnly);
-
- case "Function":
- return ParseTypedCallback(comment, model, detectKindOnly);
- }
-
- if (model.Type == ObjectType)
- return ParseTypedObject(comment, model, detectKindOnly);
- }
- return TypeDefinitionKind.Null;
- }
-
- /// <summary>
- /// Typed object parsing
- /// </summary>
- public static TypeDefinitionKind ParseTypedObject(string comment, MemberModel model)
- {
- return ParseTypedObject(comment, model, false);
- }
- public static TypeDefinitionKind ParseTypedObject(string comment, MemberModel model, bool detectKindOnly)
- {
- if (model != null && comment != null && comment != "")
- {
- Match m = ASFileParserRegexes.ValidObjectType.Match(comment);
- if (m.Success)
- {
- if (!detectKindOnly)
- model.Type = TypeCommentUtils.ObjectType + "@" + m.Groups["type"].Value;
- return TypeDefinitionKind.TypedObject;
- }
- }
- return TypeDefinitionKind.Null;
- }
-
- /// <summary>
- /// Typed array parsing
- /// </summary>
- public static TypeDefinitionKind ParseTypedArray(string comment, MemberModel model)
- {
- return ParseTypedArray(comment, model, false);
- }
- public static TypeDefinitionKind ParseTypedArray(string comment, MemberModel model, bool detectKindOnly)
- {
- if (model != null && comment != null && comment != "")
- {
- Match m = ASFileParserRegexes.ValidTypeName.Match(comment);
- if (m.Success)
- {
- if (!detectKindOnly)
- model.Type = "Array@" + m.Groups["type"].Value;
-
- return TypeDefinitionKind.TypedArray;
- }
- }
- return TypeDefinitionKind.Null;
- }
-
- /// <summary>
- /// Typed callbck parsing
- /// </summary>
- public static TypeDefinitionKind ParseTypedCallback(string comment, MemberModel model)
- {
- return ParseTypedCallback(comment, model, false);
- }
- public static TypeDefinitionKind ParseTypedCallback(string comment, MemberModel model, bool detectKindOnly)
- {
- if (model != null && comment != null && comment != ""
- && (model.Flags & FlagType.Function) == 0)
- {
- MemberModel fnModel = extractTypedCallbackModel(comment);
- if (fnModel != null)
- {
- if (!detectKindOnly)
- {
- model.Type = fnModel.Type;
- model.Flags |= FlagType.Function;
- model.Parameters = fnModel.Parameters;
- if (model.Access == 0)
- {
- if (model.Namespace == "internal")
- {
- if ((model.Access & Visibility.Public) == 0)
- model.Access = Visibility.Internal;
-
- model.Namespace = "";
- }
- else model.Access = Visibility.Public;
- }
- }
- return TypeDefinitionKind.TypedCallback;
- }
- }
- return TypeDefinitionKind.Null;
- }
-
-
- //---------------------
- // PRIVATE METHODS
- //---------------------
-
- /// <summary>
- /// String randomer
- /// </summary>
- private static string getRandomStringRepl()
- {
- random.NextDouble();
- return "StringRepl" + random.Next(0xFFFFFFF).ToString();
- }
-
- /// <summary>
- /// TypedCallback model extracting
- /// </summary>
- private static MemberModel extractTypedCallbackModel(string comment)
- {
- if (comment == null || comment.Length == 0)
- return null;
-
- int idxBraceOp = comment.IndexOf("(");
- int idxBraceCl = comment.IndexOf(")");
-
- if (idxBraceOp != 0 || idxBraceCl < 1)
- return null;
-
- // replace strings by temp replacements
- MatchCollection qStrMatches = ASFileParserRegexes.QuotedString.Matches(comment);
- Dictionary<String, String> qStrRepls = new Dictionary<string, string>();
- int i = qStrMatches.Count;
- while (i-- > 0)
- {
- String strRepl = getRandomStringRepl();
- qStrRepls.Add(strRepl, qStrMatches[i].Value);
- comment = comment.Substring(0, qStrMatches[i].Index) + strRepl + comment.Substring(qStrMatches[i].Index + qStrMatches[i].Length);
- }
-
- // refreshing
- idxBraceOp = comment.IndexOf("(");
- idxBraceCl = comment.IndexOf(")");
-
- if (idxBraceOp != 0 || comment.LastIndexOf("(") != idxBraceOp
- || idxBraceCl < 0 || comment.LastIndexOf(")") != idxBraceCl)
- return null;
-
- MemberModel fm = new MemberModel("unknown", "*", FlagType.Function, Visibility.Default);
- fm.Parameters = new List<MemberModel>();
-
- // return type
- Match m = ASFileParserRegexes.FunctionType.Match(comment.Substring(idxBraceCl));
- if (m.Success)
- fm.Type = m.Groups["fType"].Value;
-
- // parameters
- String pBody = comment.Substring(idxBraceOp, 1 + idxBraceCl - idxBraceOp);
- MatchCollection pMatches = ASFileParserRegexes.Parameter.Matches(pBody);
- int l = pMatches.Count;
- for (i = 0; i < l; i++)
- {
- string pName = pMatches[i].Groups["pName"].Value;
- if (pName != null && pName.Length > 0)
- {
- foreach (KeyValuePair<String,String> replEntry in qStrRepls)
- {
- if (pName.IndexOf(replEntry.Key) > -1)
- {
- pName = "[COLOR=#F00][I]InvalidName[/I][/COLOR]";
- break;
- }
- }
- }
-
- string pType = pMatches[i].Groups["pType"].Value;
- if (pType != null && pType.Length > 0)
- {
- foreach (KeyValuePair<String,String> replEntry in qStrRepls)
- {
- if (pType.IndexOf(replEntry.Key) > -1)
- {
- pType = "[COLOR=#F00][I]InvalidType[/I][/COLOR]";
- break;
- }
- }
- }
-
- string pVal = pMatches[i].Groups["pVal"].Value;
- if (pVal != null && pVal.Length > 0)
- {
- if (qStrRepls.ContainsKey(pVal))
- {
- pVal = qStrRepls[pVal];
- }
- else
- {
- foreach (KeyValuePair<String,String> replEntry in qStrRepls)
- {
- if (pVal.IndexOf(replEntry.Key) > -1)
- {
- pVal = "[COLOR=#F00][I]InvalidValue[/I][/COLOR]";
- break;
- }
- }
- }
- }
- else
- {
- pVal = null;
- }
-
- MemberModel pModel = new MemberModel();
- pModel.Name = pName;
- pModel.Type = pType;
- pModel.Value = pVal;
- pModel.Flags = FlagType.ParameterVar;
- pModel.Access = Visibility.Default;
-
- fm.Parameters.Add(pModel);
- }
- return fm;
- }
- }
- //
- #endregion
-
- #region ASFileParserRegexes class
- //
- public class ASFileParserRegexes
- {
- public static readonly Regex Spaces = new Regex("\\s+", RegexOptions.Compiled);
- public static readonly Regex Region = new Regex(@"^(#|{)[ ]?region[:\\s]*(?<name>[^\r\n]*)", RegexOptions.Compiled);
- public static readonly Regex QuotedString = new Regex("(\"(\\\\.|[^\"\\\\])*\")|('(\\\\.|[^'\\\\])*')", RegexOptions.Compiled);
- public static readonly Regex FunctionType = new Regex(@"\)\s*\:\s*(?<fType>[\w\$\.\<\>\@]+)", RegexOptions.Compiled);
- public static readonly Regex ValidTypeName = new Regex("^(\\s*of\\s*)?(?<type>[\\w.\\$]*)$", RegexOptions.Compiled);
- public static readonly Regex ValidObjectType = new Regex("^(?<type>[\\w.,\\$]*)$", RegexOptions.Compiled);
- public static readonly Regex Import = new Regex("^[\\s]*import[\\s]+(?<package>[\\w.]+)",
- ASFileParserRegexOptions.MultilineComment);
- public static readonly Regex Parameter = new Regex(@"[\(,]\s*((?<pName>(\.\.\.)?[\w\$]+)\s*(\:\s*(?<pType>[\w\$\*\.\<\>\@]+))?(\s*\=\s*(?<pVal>[^\,\)]+))?)",
- RegexOptions.Compiled);
- public static readonly Regex BalancedBraces = new Regex("{[^{}]*(((?<Open>{)[^{}]*)+((?<Close-Open>})[^{}]*)+)*(?(Open)(?!))}",
- ASFileParserRegexOptions.SinglelineComment);
-
- private const string typeChars = @"[\w\$][\w\d\$]*";
- private const string typeClsf = @"(\s*(?<Classifier>" + typeChars + @"(\." + typeChars + ")*" + @"(\:\:?" + typeChars + ")?" + @")\s*)";
- private const string typeComment = @"(\s*\/\*(?<Comment>.*)\*\/\s*)";
- public static readonly Regex TypeDefinition = new Regex(@"^((" + typeClsf + typeComment + ")|(" + typeComment + typeClsf + ")|(" + typeClsf + "))$",
- RegexOptions.Compiled);
- }
- //
- #endregion
-
- #region ASFileParserRegexOptions class
- //
- public class ASFileParserRegexOptions
- {
- public const RegexOptions MultilineComment = RegexOptions.Compiled | RegexOptions.Multiline;
- public const RegexOptions SinglelineComment = RegexOptions.Compiled | RegexOptions.Singleline;
- }
- //
- #endregion
-
- #region ASFileParserUtils class
- //
- public class ASFileParserUtils
- {
- /// <summary>
- /// Contributor: i.o.
- /// Description: Extracts from plain string a type classifier and type comment
- /// Example:
- /// typeDefinition: "Array/*String*/" or "Array[spaces]/*String*/" or "/*String*/Array"
- /// typeClassifier: "Array"
- /// typeComment: "String"
- /// </summary>
- public static bool ParseTypeDefinition(string typeDefinition, out string typeClassifier, out string typeComment)
- {
- typeClassifier = null;
- typeComment = null;
-
- if (String.IsNullOrEmpty(typeDefinition))
- return false;
-
- Match m = ASFileParserRegexes.TypeDefinition.Match(typeDefinition);
- if (!m.Success)
- return false;
-
- typeClassifier = m.Groups["Classifier"].Value;
-
- if (m.Groups["Comment"].Success)
- typeComment = m.Groups["Comment"].Value;
-
- return true;
- }
-
- public static TypeDefinitionKind ParseTypeDefinitionInto(string typeDefinition, MemberModel model)
- {
- return ParseTypeDefinitionInto(typeDefinition, model, true, true);
- }
- public static TypeDefinitionKind ParseTypeDefinitionInto(string typeDefinition, MemberModel model, bool parseCommon, bool parseGeneric)
- {
- if (String.IsNullOrEmpty(typeDefinition))
- return TypeDefinitionKind.Null;
-
- if (typeDefinition.IndexOf("/*") < 0 || typeDefinition.IndexOf("*/") < 0)
- {
- if (!parseCommon)
- return TypeDefinitionKind.Null;
-
- model.Type = typeDefinition.Replace(":", ".");
- if (model.Type.IndexOf('$') > 0) model.Type = model.Type.Replace("$", ".<") + ">";
- return TypeDefinitionKind.Simple;
- }
-
- if (!parseGeneric)
- return TypeDefinitionKind.Null;
-
- string typeClassifier;
- string typeComment;
- if (!ASFileParserUtils.ParseTypeDefinition(typeDefinition, out typeClassifier, out typeComment))
- return TypeDefinitionKind.Null;
-
- model.Type = typeClassifier;
-
- return TypeCommentUtils.Parse(typeComment, model);
- }
- }
- //
- #endregion
-
- /// <summary>
- /// Old & clumsy AS2/AS3/haxe file parser - beware!
- /// </summary>
- public class ASFileParser
- {
-
- #region public methods
- static private PathModel cachedPath;
- static private DateTime cacheLastWriteTime;
-
- static public void ParseCacheFile(PathModel inPath, string file, IASContext inContext)
- {
- lock (typeof(ASFileParser))
- {
- cachedPath = inPath;
- ParseFile(file, inContext);
- cachedPath = null;
- }
- }
-
- static public FileModel ParseFile(string file, IASContext inContext)
- {
- FileModel fileModel = new FileModel(file);
- fileModel.Context = inContext;
- return ParseFile(fileModel);
- }
-
- static public FileModel ParseFile(FileModel fileModel)
- {
- string src = "";
- // parse file
- if (fileModel.FileName.Length > 0)
- {
- if (File.Exists(fileModel.FileName))
- {
- src = PluginCore.Helpers.FileHelper.ReadFile(fileModel.FileName);
- ASFileParser parser = new ASFileParser();
- fileModel.LastWriteTime = File.GetLastWriteTime(fileModel.FileName);
- if (cachedPath != null)
- cacheLastWriteTime = fileModel.LastWriteTime;
- parser.ParseSrc(fileModel, src);
- }
- // the file is not available (for the moment?)
- else if (Path.GetExtension(fileModel.FileName).Length > 0)
- {
- fileModel.OutOfDate = true;
- }
- }
- // this is a package
- else
- {
- // ignore
- }
- return fileModel;
- }
- #endregion
-
- #region parser context
- const int COMMENTS_BUFFER = 4096;
- const int TOKEN_BUFFER = 1024;
- const int VALUE_BUFFER = 1024;
-
- // parser context
- private FileModel model;
- private int version;
- private bool haXe;
- private bool tryPackage;
- private bool hasPackageSection;
- private FlagType context;
- private FlagType modifiers;
- private FlagType curModifiers;
- //private int modifiersPos;
- private int line;
- private int modifiersLine;
- private bool foundColon;
- private bool inParams;
- private bool inEnum;
- private bool inTypedef;
- private bool inGeneric;
- private bool inValue;
- private bool inConst;
- private bool inType;
- private bool inAnonType;
- private bool flattenNextBlock;
- private FlagType foundKeyword;
- private Token valueKeyword;
- private MemberModel valueMember;
- private Token curToken;
- private Token prevToken;
- private MemberModel curMember;
- private MemberModel curMethod;
- private Visibility curAccess;
- private string curNamespace;
- private ClassModel curClass;
- private string lastComment;
- private string curComment;
- private bool isBlockComment;
- private ContextFeatures features;
- #endregion
-
- #region tokenizer
-
- public bool ScriptMode;
-
- public ContextFeatures Features
- {
- get { return features; }
- }
-
- public ASFileParser()
- {
- features = new ContextFeatures();
- }
-
- /// <summary>
- /// Rebuild a file model with the source provided
- /// </summary>
- /// <param name="fileModel">Model</param>
- /// <param name="ba">Source</param>
- ///
- public void ParseSrc(FileModel fileModel, string ba)
- {
- ParseSrc(fileModel, ba, true);
- }
- public void ParseSrc(FileModel fileModel, string ba, bool allowBaReExtract)
- {
- //TraceManager.Add("Parsing " + Path.GetFileName(fileModel.FileName));
- model = fileModel;
- model.OutOfDate = false;
- model.CachedModel = false;
-
- // pre-filtering
- if (allowBaReExtract && model.HasFiltering && model.Context != null)
- ba = model.Context.FilterSource(fileModel.FileName, ba);
-
- model.InlinedIn = null;
- model.InlinedRanges = null;
-
- // language features
- if (model.Context != null) features = model.Context.Features;
- model.Imports.Clear();
- model.Classes.Clear();
- model.Members.Clear();
- model.Namespaces.Clear();
- model.Regions.Clear();
- model.PrivateSectionIndex = 0;
- model.Package = "";
- model.MetaDatas = null;
-
- // state
- int len = ba.Length;
- if (len < 0)
- return;
- int i = 0;
- line = 0;
-
- // when parsing cache file including multiple files
- resetParser:
-
- char c1;
- char c2;
- int matching = 0;
- bool isInString = false;
- int inString = 0;
- int braceCount = 0;
- bool inCode = true;
-
- // comments
- char[] commentBuffer = new char[COMMENTS_BUFFER];
- int commentLength = 0;
- lastComment = null;
- curComment = null;
-
- // tokenisation
- tryPackage = true;
- hasPackageSection = false;
- haXe = model.haXe;
- TypeCommentUtils.ObjectType = haXe ? "Dynamic" : "Object";
- version = (haXe) ? 4 : 1;
- curToken = new Token();
- prevToken = new Token();
- int tokPos = 0;
- int tokLine = 0;
- curMethod = null;
- curMember = null;
- valueKeyword = null;
- valueMember = null;
- curModifiers = 0;
- curNamespace = "internal";
- curAccess = 0;
-
- char[] buffer = new char[TOKEN_BUFFER];
- int length = 0;
- char[] valueBuffer = new char[VALUE_BUFFER];
- int valueLength = 0;
- int paramBraceCount = 0;
- int paramTempCount = 0;
- int paramParCount = 0;
- int paramSqCount = 0;
-
- bool hadWS = true;
- bool hadDot = false;
- inParams = false;
- inEnum = false;
- inTypedef = false;
- inValue = false;
- inConst = false;
- inType = false;
- inGeneric = false;
- inAnonType = false;
-
- bool addChar = false;
- int evalToken = 0;
- //bool evalKeyword = true;
- context = 0;
- modifiers = 0;
- foundColon = false;
-
- bool handleDirectives = features.hasDirectives || cachedPath != null;
- bool inlineDirective = false;
-
- while (i < len)
- {
- c1 = ba[i++];
- isInString = (inString > 0);
-
- /* MATCH COMMENTS / STRING LITERALS */
-
- switch (matching)
- {
- // look for comment block/line and preprocessor commands
- case 0:
- if (!isInString)
- {
- // new comment
- if (c1 == '/' && i < len)
- {
- c2 = ba[i];
- if (c2 == '/')
- {
- // Check if this this is a /// comment
- if (i + 1 < len && ba[i + 1] == '/')
- {
- // This is a /// comment
- matching = 4;
- isBlockComment = true;
- i++;
- }
- else
- {
- // This is a regular comment
- matching = 1;
- isBlockComment = false;
- }
- inCode = false;
- i++;
- continue;
- }
- else if (c2 == '*')
- {
- isBlockComment = (i + 1 < len && ba[i + 1] == '*');
- matching = 2;
- inCode = false;
- i++;
- while (i < len - 1)
- {
- c2 = ba[i];
- if (c2 == '*' && ba[i + 1] != '/') i++;
- else break;
- }
- continue;
- }
- }
- // don't look for comments in strings
- else if (c1 == '"')
- {
- isInString = true;
- inString = 1;
- }
- else if (c1 == '\'')
- {
- isInString = true;
- inString = 2;
- }
- // preprocessor statements
- else if (c1 == '#' && handleDirectives)
- {
- int ls = i - 2;
- inlineDirective = false;
- while (ls > 0)
- {
- c2 = ba[ls--];
- if (c2 == 10 || c2 == 13) break;
- else if (c2 > 32) { inlineDirective = true; break; }
- }
- c2 = ba[i];
- if (i < 2 || ba[i - 2] < 33 && c2 >= 'a' && c2 <= 'z')
- {
- matching = 3;
- inCode = false;
- continue;
- }
- }
- }
- // end of string
- else if (isInString)
- {
- if (c1 == '\\') { i++; continue; }
- else if (c1 == 10 || c1 == 13) inString = 0;
- else if ((inString == 1) && (c1 == '"')) inString = 0;
- else if ((inString == 2) && (c1 == '\'')) inString = 0;
-
- // extract "include" declarations
- if (inString == 0 && length == 7 && context == 0)
- {
- string token = new string(buffer, 0, length);
- if (token == "include")
- {
- string inc = ba.Substring(tokPos, i - tokPos);
- if (model.MetaDatas == null) model.MetaDatas = new List<ASMetaData>();
- ASMetaData meta = new ASMetaData("Include");
- meta.ParseParams(inc);
- model.MetaDatas.Add(meta);
- }
- }
- }
- break;
-
- // skip commented line
- case 1:
- if (c1 == 10 || c1 == 13)
- {
- // ignore single comments
- commentLength = 0;
- inCode = true;
- matching = 0;
- }
- break;
-
- // skip commented block
- case 2:
- if (c1 == '*')
- {
- bool end = false;
- while (i < len)
- {
- c2 = ba[i];
- if (c2 == '\\') { i++; continue; }
- if (c2 == '/')
- {
- end = true;
- break;
- }
- else if (c2 == '*') i++;
- else break;
- }
- if (end)
- {
- lastComment = (commentLength > 0) ? new string(commentBuffer, 0, commentLength) : null;
- // TODO parse for TODO statements?
- commentLength = 0;
- inCode = true;
- matching = 0;
- i++;
- continue;
- }
- }
- break;
-
- // directive/preprocessor statement
- case 3:
- if (c1 == 10 || c1 == 13 || (inlineDirective && c1 <= 32))
- {
- if (commentLength > 0)
- {
- string directive = new string(commentBuffer, 0, commentLength);
- if (directive.StartsWith("if"))
- {
- inCode = true;
- }
- else if (directive.StartsWith("else"))
- {
- inCode = true;
- }
- else inCode = true;
-
- // FD cache custom directive
- if (cachedPath != null && directive.StartsWith("file-cache "))
- {
- // parsing done!
- FinalizeModel();
-
- // next model
- string realFile = directive.Substring(11);
- FileModel newModel = new FileModel(realFile, cacheLastWriteTime);
- newModel.CachedModel = true;
- newModel.Context = model.Context;
- haXe = newModel.haXe;
- if (!cachedPath.HasFile(realFile) && File.Exists(realFile))
- {
- newModel.OutOfDate = (File.GetLastWriteTime(realFile) > cacheLastWriteTime);
- cachedPath.AddFile(newModel);
- }
- model = newModel;
- goto resetParser; // loop
- }
- }
- else inCode = true;
- commentLength = 0;
- matching = 0;
- }
-
- break;
-
- // We are inside a /// comment
- case 4:
- {
- bool end = false;
- bool skipAhead = false;
-
- // See if we just ended a line
- if (2 <= i && (ba[i - 2] == 10 || ba[i - 2] == 13))
- {
- // Check ahead to the next line, see if it has a /// comment on it too.
- // If it does, we want to continue the comment with that line. If it
- // doesn't, then this comment is finished and we will set end to true.
- for (int j = i + 1; j < len; ++j)
- {
- // Skip whitespace
- char twoBack = ba[j - 2];
- if (' ' != twoBack && '\t' != twoBack)
- {
- if ('/' == twoBack && '/' == ba[j - 1] && '/' == ba[j])
- {
- // There is a comment ahead. Move up to it so we can gather the
- // rest of the comment
- i = j + 1;
- skipAhead = true;
- break;
- }
- else
- {
- // Not a comment! We're done!
- end = true;
- break;
- }
- }
- }
- }
- if (end)
- {
- // The comment is over and we want to write it out
- lastComment = (commentLength > 0) ? new string(commentBuffer, 0, commentLength).Trim() : null;
- commentLength = 0;
- inCode = true;
- matching = 0;
-
- // Back up i so we can start gathering comments from right after the line break
- --i;
- continue;
- }
- if (skipAhead)
- {
- // We just hit another /// and are skipping up to right after it.
- continue;
- }
- break;
- }
- }
-
- /* LINE/COLUMN NUMBER */
-
- if (c1 == 10 || c1 == 13)
- {
- if (cachedPath == null) line++; // cache breaks line count
- if (c1 == 13 && i < len && ba[i] == 10) i++;
- }
-
-
- /* SKIP CONTENT */
-
- if (!inCode)
- {
- // store comments
- if (matching == 2 || (matching == 3 && handleDirectives) || matching == 4)
- {
- if (commentLength < COMMENTS_BUFFER) commentBuffer[commentLength++] = c1;
- }
- else if (matching == 1 && (c1 == '#' || c1 == '{'))
- {
- commentBuffer[commentLength++] = c1;
- while (i < len)
- {
- c2 = ba[i];
- if (commentLength < COMMENTS_BUFFER) commentBuffer[commentLength++] = c2;
- if (c2 == 10 || c2 == 13)
- break;
- i++;
- }
-
- string comment = new String(commentBuffer, 0, commentLength);
- Match match = ASFileParserRegexes.Region.Match(comment);
- if (match.Success)
- {
- string regionName = match.Groups["name"].Value.Trim();
- MemberModel region = new MemberModel(regionName, String.Empty, FlagType.Declaration, Visibility.Default);
- region.LineFrom = region.LineTo = line;
- model.Regions.Add(region);
- }
- }
- continue;
- }
- else if (isInString)
- {
- // store parameter default value
- if (inValue && valueLength < VALUE_BUFFER)
- valueBuffer[valueLength++] = c1;
- continue;
- }
- if (braceCount > 0 && !inValue)
- {
- if (c1 == '/')
- {
- LookupRegex(ref ba, ref i);
- }
- else if (c1 == '}')
- {
- lastComment = null;
- braceCount--;
- if (braceCount == 0 && curMethod != null)
- {
- curMethod.LineTo = line;
- curMethod = null;
- }
- }
- else if (c1 == '{') braceCount++;
- // escape next char
- else if (c1 == '\\') i++;
- continue;
- }
-
-
- /* PARSE DECLARATION VALUES/TYPES */
-
- if (inValue)
- {
- bool stopParser = false;
- bool valueError = false;
- if (inType && !inAnonType && !inGeneric && !Char.IsLetterOrDigit(c1) && ".{}-><".IndexOf(c1) < 0)
- {
- inType = false;
- inValue = false;
- inGeneric = false;
- valueLength = 0;
- length = 0;
- context = 0;
- }
- else if (c1 == '{')
- {
- paramBraceCount++;
- stopParser = true;
- }
- else if (c1 == '}')
- {
- if (paramBraceCount > 0) { paramBraceCount--; stopParser = true; }
- else valueError = true;
- }
- else if (c1 == '(')
- {
- paramParCount++;
- stopParser = true;
- }
- else if (c1 == ')')
- {
- if (paramParCount > 0) { paramParCount--; stopParser = true; }
- else valueError = true;
- }
- else if (c1 == '[') paramSqCount++;
- else if (c1 == ']')
- {
- if (paramSqCount > 0) { paramSqCount--; stopParser = true; }
- else valueError = true;
- }
- else if (c1 == '<')
- {
- if (inType) inGeneric = true;
- paramTempCount++;
- }
- else if (c1 == '>')
- {
- if (ba[i - 2] == '-') { /*haxe method signatures*/ }
- else if (paramTempCount > 0)
- {
- paramTempCount--;
- stopParser = true;
- }
- else valueError = true;
- }
- else if (c1 == '/')
- {
- int i0 = i;
- if (LookupRegex(ref ba, ref i))
- {
- valueBuffer[valueLength++] = '/';
- for (; i0 < i; i0++)
- if (valueLength < VALUE_BUFFER - 1) valueBuffer[valueLength++] = ba[i0];
- valueBuffer[valueLength++] = '/';
- continue;
- }
- }
- else if (inValue && (inParams || inType || inConst)
- && c1 == '/' && valueLength == 0) // lookup native regex
- {
- int itemp = i;
- valueBuffer[valueLength++] = '/';
- while (valueLength < VALUE_BUFFER && i < len)
- {
- c1 = ba[i++];
- if (c1 == '\n' || c1 == '\r')
- {
- valueLength = 0;
- i = itemp;
- break;
- }
- valueBuffer[valueLength++] = c1;
- if (c1 == '\\' && i < len)
- {
- c1 = ba[i++];
- valueBuffer[valueLength++] = c1;
- }
- else if (c1 == '/') break;
- }
- }
- else if ((c1 == ':' || c1 == ',') && paramBraceCount > 0) stopParser = true;
-
- // end of value
- if ((valueError || (!stopParser && paramBraceCount == 0 && paramParCount == 0 && paramSqCount == 0 && paramTempCount == 0))
- && (c1 == ',' || c1 == ';' || c1 == '}' || c1 == '\r' || c1 == '\n' || (inParams && c1 == ')') || inType))
- {
- if (!inType && (!inValue || c1 != ','))
- {
- length = 0;
- context = 0;
- }
- inValue = false;
- inGeneric = false;
- //if (valueLength < VALUE_BUFFER) valueBuffer[valueLength++] = c1;
- }
-
- // in params, store the default value
- else if ((inParams || inType || inConst) && valueLength < VALUE_BUFFER)
- {
- if (c1 <= 32)
- {
- if (valueLength > 0 && valueBuffer[valueLength - 1] != ' ')
- valueBuffer[valueLength++] = ' ';
- }
- else valueBuffer[valueLength++] = c1;
- }
-
- // detect keywords
- if (!Char.IsLetterOrDigit(c1))
- {
- // escape next char
- if (c1 == '\\' && i < len)
- {
- c1 = ba[i++];
- if (valueLength < VALUE_BUFFER) valueBuffer[valueLength++] = c1;
- continue;
- }
- if (stopParser) continue;
- else if (valueError && c1 == ')') inValue = false;
- else if (inType && inGeneric && (c1 == '<' || c1 == '.')) continue;
- else if (inAnonType) continue;
- hadWS = true;
- }
- }
-
- // store type / parameter value
- if (!inValue && valueLength > 0)
- {
- string param = /*(valueBuffer[0] == '{' && valueBuffer[0] != '[') ? "..."
- :*/ new string(valueBuffer, 0, valueLength);
-
- // get text before the last keyword found
- if (valueKeyword != null)
- {
- int p = param.LastIndexOf(valueKeyword.Text);
- if (p > 0) param = param.Substring(0, p).TrimEnd();
- }
-
- if (curMember == null)
- {
- if (inType)
- {
- prevToken.Text = curToken.Text;
- prevToken.Line = curToken.Line;
- prevToken.Position = curToken.Position;
- curToken.Text = param;
- curToken.Line = tokLine;
- curToken.Position = tokPos;
- EvalToken(true, true/*false*/, i - 1 - valueLength);
- evalToken = 0;
- }
- }
- else if (inType)
- {
- foundColon = false;
- if (haXe)
- {
- if (param.EndsWith("}") || param.Contains(">"))
- {
- param = ASFileParserRegexes.Spaces.Replace(param, "");
- param = param.Replace(",", ", ");
- param = param.Replace("->", " -> ");
- }
- }
- curMember.Type = param;
- }
- // AS3 const or method parameter's default value
- else if (version > 2 && (curMember.Flags & FlagType.Variable) > 0)
- {
- if (inParams || inConst) curMember.Value = param;
- curMember.LineTo = line;
- if (c1 == '\r' || c1 == '\n') curMember.LineTo--;
- if (inConst && c1 != ',')
- {
- context = 0;
- inConst = false;
- }
- }
- //
- valueLength = 0;
- if (!inParams && !(inConst && context != 0) && c1 != '{') continue;
- else length = 0;
- }
-
- /* TOKENIZATION */
-
- // whitespace
- if (c1 <= 32)
- {
- hadWS = true;
- continue;
- }
- // a dot can be in an identifier
- if (c1 == '.')
- {
- if (length > 0 || (inParams && version == 3))
- {
- hadWS = false;
- hadDot = true;
- addChar = true;
- if (!inValue && context == FlagType.Variable && !foundColon)
- {
- bool keepContext = inParams && (length == 0 || buffer[0] == '.');
- if (!keepContext) context = 0;
- }
- }
- else continue;
- }
- else
- {
- // should we evaluate the token?
- if (hadWS && !hadDot && !inGeneric && length > 0)
- {
- evalToken = 1;
- }
- hadWS = false;
- hadDot = false;
- bool shortcut = true;
-
- // valid char for keyword
- if (c1 >= 'a' && c1 <= 'z')
- {
- addChar = true;
- }
- else
- {
- // valid chars for identifiers
- if (c1 >= 'A' && c1 <= 'Z')
- {
- addChar = true;
- }
- else if (c1 == '$' || c1 == '_')
- {
- addChar = true;
- }
- else if (length > 0)
- {
- if (c1 >= '0' && c1 <= '9')
- {
- addChar = true;
- }
- else if (c1 == '*' && context == FlagType.Import)
- {
- addChar = true;
- }
- // haXe generics
- else if (features.hasGenerics && c1 == '<')
- {
- if (!inValue && i > 2 && length > 1 && i < len - 3
- && Char.IsLetterOrDigit(ba[i - 3]) && (Char.IsLetter(ba[i]) || (haXe && ba[i] == '{'))
- && (Char.IsLetter(buffer[0]) || buffer[0] == '_'))
- {
- if (curMember == null)
- {
- evalToken = 0;
- inGeneric = true;
- addChar = true;
- }
- else
- {
- evalToken = 0;
- inGeneric = true;
- inValue = true;
- inType = true;
- inAnonType = false;
- valueLength = 0;
- for (int j = 0; j < length; j++)
- …
Large files files are truncated, but you can click here to view the full file