public int CompareTo(object obj) { if (!(obj is ASMetaData)) { throw new InvalidCastException("This object is not of type ASMetaData"); } ASMetaData meta = obj as ASMetaData; if (Kind == ASMetaKind.Event && meta.Kind == ASMetaKind.Event) { return(Params["type"].CompareTo(meta.Params["type"])); } return(Name.CompareTo(meta.Name)); }
private bool LookupMeta(ref string ba, ref int i) { int len = ba.Length; int i0 = i; int line0 = line; int inString = 0; int parCount = 0; bool isComplex = false; while (i < len) { char c = ba[i]; if (c == 10 || c == 13) { if (cachedPath == null) line++; // cache breaks line count if (c == 13 && i < len && ba[i + 1] == 10) i++; } if (inString == 0) { if (c == '"') inString = 1; else if (c == '\'') inString = 2; else if ("{;[".IndexOf(c) >= 0) { i = i0; line = line0; return false; } else if (c == '(') parCount++; else if (c == ')') { parCount--; if (parCount < 0) return false; isComplex = true; } else if (c == ']') break; } else if (inString == 1 && c == '"') inString = 0; else if (inString == 2 && c == '\'') inString = 0; else if (inString > 0 && (c == 10 || c == 13)) inString = 0; i++; } string meta = ba.Substring(i0, i - i0); ASMetaData md = new ASMetaData(isComplex ? meta.Substring(0, meta.IndexOf('(')) : meta); md.LineFrom = line0; md.LineTo = line; if (isComplex) { meta = meta.Substring(meta.IndexOf('(') + 1); md.ParseParams(meta.Substring(0, meta.Length - 1)); if (lastComment != null && isBlockComment && (md.Name == "Event" || md.Name == "Style")) { md.Comments = lastComment; lastComment = null; } else lastComment = null; } if (model.MetaDatas == null) model.MetaDatas = new List<ASMetaData>(); model.MetaDatas.Add(md); return 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; if (model.Context != null) features = model.Context.Features; if (features != null && features.hasModules) model.Module = Path.GetFileNameWithoutExtension(model.FileName); // pre-filtering if (allowBaReExtract && model.HasFiltering && model.Context != null) ba = model.Context.FilterSource(fileModel.FileName, ba); model.InlinedIn = null; model.InlinedRanges = null; // language 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; inAbstract = 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 if (directive.StartsWith("end")) { inCode = true; // directive end matching = 0; } 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 = model.Context != null ? model.Context.CreateFileModel(realFile) : new FileModel(realFile); newModel.LastWriteTime = cacheLastWriteTime; newModel.CachedModel = true; if (features != null && features.hasModules) newModel.Module = Path.GetFileNameWithoutExtension(realFile); 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 == '{') { if (!inType || valueLength == 0 || valueBuffer[valueLength - 1] == '<' || paramBraceCount > 0) { 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 (i > 1 && ba[i - 2] == '<') paramTempCount = 0; // a << b else { 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) && valueLength < VALUE_BUFFER - 3) { valueBuffer[valueLength++] = '/'; for (; i0 < i; i0++) if (valueLength < VALUE_BUFFER - 2) 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; valueMember = null; 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; } // AS3/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; if (inGeneric) paramTempCount++; else { paramTempCount = 1; inGeneric = true; } addChar = true; } else { evalToken = 0; inGeneric = true; inValue = true; inType = true; inAnonType = false; valueLength = 0; for (int j = 0; j < length; j++) valueBuffer[valueLength++] = buffer[j]; valueBuffer[valueLength++] = c1; length = 0; paramBraceCount = 0; paramParCount = 0; paramSqCount = 0; paramTempCount = 1; continue; } } } else if (inGeneric && (c1 == ',' || c1 == '.' || c1 == '-' || c1 == '>' || c1 == ':')) { hadWS = false; hadDot = false; evalToken = 0; if (!inValue) { addChar = true; if (c1 == '>' && inGeneric) { if (paramTempCount > 0) paramTempCount--; if (paramTempCount == 0 && paramBraceCount == 0 && paramSqCount == 0 && paramParCount == 0) inGeneric = false; } } } else { evalToken = 2; shortcut = false; } } // star is valid in import statements else if (c1 == '*' && version == 3) { addChar = true; } // conditional haXe parameter else if (c1 == '?' && haXe && inParams && length == 0) { addChar = true; } else shortcut = false; } // eval this word if (evalToken > 0) { prevToken.Text = curToken.Text; prevToken.Line = curToken.Line; prevToken.Position = curToken.Position; curToken.Text = new string(buffer, 0, length); curToken.Line = tokLine; curToken.Position = tokPos; EvalToken(!inValue, (c1 != '=' && c1 != ','), i - 1 - length); length = 0; evalToken = 0; } if (!shortcut) // start of block if (c1 == '{') { if (context == FlagType.Package || context == FlagType.Class) // parse package/class block { context = 0; } else if (context == FlagType.Enum) // parse enum block { if (curClass != null && (curClass.Flags & FlagType.Enum) > 0) inEnum = true; else { context = 0; curModifiers = 0; braceCount++; // ignore block } } else if (context == FlagType.TypeDef) // parse typedef block { if (curClass != null && (curClass.Flags & FlagType.TypeDef) > 0) { inTypedef = true; if (i < len && ba[i] == '>') { buffer[0] = 'e'; buffer[1] = 'x'; buffer[2] = 't'; buffer[3] = 'e'; buffer[4] = 'n'; buffer[5] = 'd'; buffer[6] = 's'; length = 7; context = FlagType.Class; } } else { context = 0; curModifiers = 0; braceCount++; // ignore block } } else if (context == FlagType.Abstract) // parse abstract block { if (curClass != null && (curClass.Flags & FlagType.Abstract) > 0) inAbstract = true; else { context = 0; curModifiers = 0; braceCount++; // ignore block } } else if (foundColon && haXe && length == 0) // copy haXe anonymous type { inValue = true; inType = true; inAnonType = true; valueLength = 0; valueBuffer[valueLength++] = c1; paramBraceCount = 1; paramParCount = 0; paramSqCount = 0; paramTempCount = 0; continue; } else if (foundConstant) // start config block { flattenNextBlock++; foundConstant = false; context = 0; } else if (ScriptMode) // not in a class, parse if/for/while/do blocks { context = 0; } else braceCount++; // ignore block } // end of block else if (c1 == '}') { curComment = null; foundColon = false; foundConstant = false; if (flattenNextBlock > 0) // content of this block was parsed { flattenNextBlock--; } // outside of a method, the '}' ends the current class else if (curClass != null) { if (curClass != null) curClass.LineTo = line; curClass = null; inEnum = false; inTypedef = false; inAbstract = false; } else { if (hasPackageSection && model.PrivateSectionIndex == 0) model.PrivateSectionIndex = line + 1; } } // member type declaration else if (c1 == ':' && !inValue && !inGeneric) { foundColon = curMember != null && curMember.Type == null; // recognize compiler config block if (!foundColon && braceCount == 0 && i < len - 2 && ba[i] == ':' && Char.IsLetter(ba[i + 1])) foundConstant = true; } // next variable declaration else if (c1 == ',') { if ((context == FlagType.Variable || context == FlagType.TypeDef) && curMember != null) { curAccess = curMember.Access; foundKeyword = FlagType.Variable; foundColon = false; lastComment = null; } else if (context == FlagType.Class && prevToken.Text == "implements") { curToken.Text = "implements"; foundKeyword = FlagType.Implements; } } else if (c1 == '(') { if (!inValue && context == FlagType.Variable && curToken.Text != "catch" && (!haXe || curToken.Text != "for")) if (haXe && curMember != null && valueLength == 0) // haXe properties { curMember.Flags -= FlagType.Variable; curMember.Flags |= FlagType.Getter | FlagType.Setter; context = FlagType.Function; } else context = 0; // beginning of method parameters if (context == FlagType.Function) { context = FlagType.Variable; inParams = true; inGeneric = false; if (valueMember != null && curMember == null) { valueLength = 0; //valueMember.Flags -= FlagType.Variable; ??? valueMember.Flags = FlagType.Function; curMethod = curMember = valueMember; valueMember = null; } else if (curMember == null) { context = FlagType.Function; if ((curModifiers & FlagType.Getter) > 0) { curModifiers -= FlagType.Getter; EvalToken(true, false, i); curMethod = curMember; context = FlagType.Variable; } else if ((curModifiers & FlagType.Setter) > 0) { curModifiers -= FlagType.Setter; EvalToken(true, false, i); curMethod = curMember; context = FlagType.Variable; } else { inParams = false; context = 0; } } else { curMethod = curMember; } } // an Enum value with parameters else if (inEnum && curToken != null) { context = FlagType.Variable; inParams = true; curMethod = curMember ?? new MemberModel(); curMethod.Name = curToken.Text; curMethod.Flags = curModifiers | FlagType.Function | FlagType.Static; curMethod.Parameters = new List<MemberModel>(); // if (curClass != null && curMember == null) curClass.Members.Add(curMethod); } // a TypeDef method with parameters else if (inTypedef && curToken != null) { context = FlagType.Variable; inParams = true; curMethod = curMember ?? new MemberModel(); curMethod.Name = curToken.Text; curMethod.Flags = curModifiers | FlagType.Function; curMethod.Parameters = new List<MemberModel>(); // if (curClass != null && curMember == null) curClass.Members.Add(curMethod); } // an Abstract "opaque type" else if (context == FlagType.Abstract && prevToken.Text == "abstract") { foundKeyword = FlagType.Class; curModifiers = FlagType.Extends; } else if (curMember == null && curToken.Text != "catch" && (!haXe || curToken.Text != "for")) { context = 0; inGeneric = false; } } // end of statement else if (c1 == ';') { context = (inEnum) ? FlagType.Enum : 0; inGeneric = false; modifiers = 0; inParams = false; curMember = null; } // end of method parameters else if (c1 == ')' && inParams) { context = 0; if (inEnum) context = FlagType.Enum; else if (inTypedef) context = FlagType.TypeDef; modifiers = 0; inParams = false; curMember = curMethod; } // skip value of a declared variable else if (c1 == '=') { if (context == FlagType.Variable || (context == FlagType.Enum && inEnum)) { if (!inValue && curMember != null) { inValue = true; inConst = (curMember.Flags & FlagType.Constant) > 0; inType = false; inGeneric = false; paramBraceCount = 0; paramParCount = 0; paramSqCount = 0; paramTempCount = 0; valueLength = 0; valueMember = curMember; } } } // metadata else if (!inValue && c1 == '[') { if (version == 3) LookupMeta(ref ba, ref i); else if (features.hasCArrays && curMember != null && curMember.Type != null) { if (ba[i] == ']') curMember.Type = features.CArrayTemplate + "@" + curMember.Type; } } // haXe signatures: T -> T -> T else if (haXe && c1 == '-' && curMember != null) { if (ba[i] == '>' && curMember.Type != null) { curMember.Type += " ->"; foundColon = true; } } // escape next char else if (c1 == '\\') { i++; continue; } // literal regex else if (c1 == '/' && version == 3) { if (LookupRegex(ref ba, ref i)) continue; } } // put in buffer if (addChar) { if (length < TOKEN_BUFFER) buffer[length++] = c1; if (length == 1) { tokPos = i - 1; tokLine = line; } addChar = false; } } // parsing done! FinalizeModel(); // post-filtering if (cachedPath == null && model.HasFiltering && model.Context != null) model.Context.FilterSource(model); // Debug.WriteLine("out model: " + model.GenerateIntrinsic(false)); }
private static void AddEvents(FileModel aFile, BlockModel docModel, bool targetAIR, bool targetFP10) { aFile.MetaDatas = new List<ASMetaData>(); foreach (EventModel ev in docModel.Events) { if (!targetAIR && ev.IsAIR) continue; if (!targetFP10 && ev.IsFP10) continue; int p = ev.EventType.LastIndexOf('.'); string type = ev.EventType.Substring(0, p); string pname = ev.EventType.Substring(p + 1); ClassModel eClass = getClass(type); if (eClass.IsVoid()) continue; string value = '"' + ev.Name + '"'; if (eClass.Members.Items.Any<MemberModel>(item => item.Name == pname)) { ASMetaData meta = new ASMetaData("Event"); if (ev.Comment != null) meta.Comments = "\r\n\t * " + ev.Comment + "\r\n\t * @eventType " + ev.EventType; meta.ParseParams(String.Format("name=\"{0}\", type=\"{1}\"", ev.Name, type)); aFile.MetaDatas.Add(meta); } } }
private ASMetaData LookupHaxeMeta(ref string ba, ref int i) { int len = ba.Length; int i0 = i; int line0 = line; int inString = 0; int parCount = 0; bool isComplex = false; while (i < len) { char c = ba[i]; if (inString == 0) { if (c == '"') inString = 1; else if (c == '\'') inString = 2; else if ("{;[".IndexOf(c) >= 0) // Is this valid in Haxe meta? { i = i0; line = line0; return null; } else if (c == '(') parCount++; else if (c == ')') { parCount--; isComplex = true; if (parCount <= 0) break; } else if (c <= 32 && parCount <= 0) { break; } } else if (c == 10 || c == 13) { line++; if (c == 13 && i < len && ba[i + 1] == 10) i++; } else if (inString == 1 && c == '"') inString = 0; else if (inString == 2 && c == '\'') inString = 0; i++; } string meta = ba.Substring(i0, i - i0); ASMetaData md = new ASMetaData(isComplex ? meta.Substring(0, meta.IndexOf('(')) : meta); md.LineFrom = line0; md.LineTo = line; if (isComplex) { meta = meta.Substring(meta.IndexOf('(') + 1).Trim(); md.Params = new Dictionary<string, string>(); md.Params["Default"] = meta; } return md; }
private void ReadEventMeta(ASDocItem doc) { if (IsEmptyElement) return; ASMetaData meta = new ASMetaData("Event"); meta.Kind = ASMetaKind.Event; meta.Comments = ""; string eName = null; string eType = null; string eFullType = null; string eon = Name; ReadStartElement(); while (Name != eon) { if (NodeType == XmlNodeType.Element) switch (Name) { case "shortdesc": meta.Comments = ReadValue() ?? ""; break; case "apiDesc": if (meta.Comments == "") meta.Comments = ReadValue() ?? ""; break; case "apiName": eName = ReadValue(); break; case "adobeApiEventClassifier": eType = ReadValue().Replace(':', '.'); break; case "apiEventType": eFullType = ReadValue(); break; } Read(); } if (doc.Meta == null) doc.Meta = new List<ASMetaData>(); meta.Params = new Dictionary<string, string>(); meta.Params["name"] = eName; meta.Params["type"] = eType; if (eFullType != null) meta.Comments = meta.Comments.Trim() + "\n@eventType\t" + eFullType.Replace(':', '.'); meta.RawParams = String.Format("name=\"{0}\", type=\"{1}\"", eName, eType); doc.Meta.Add(meta); }
public string GenerateIntrinsic(bool caching) { StringBuilder sb = new StringBuilder(); string nl = (caching) ? "" : "\r\n"; char semi = ';'; string tab0 = (!caching && InFile.Version == 3) ? "\t" : ""; string tab = (caching) ? "" : ((InFile.Version == 3) ? "\t\t" : "\t"); bool preventVis = (bool)((this.Flags & FlagType.Interface) > 0); // SPECIAL DELEGATE /*if ((Flags & FlagType.Delegate) > 0) * { * if (Members.Count > 0) * { * MemberModel ctor = Members[0].Clone() as MemberModel; * ctor.Flags |= FlagType.Delegate; * ctor.Access = Access; * String comment = CommentDeclaration(ctor.Comments, tab0); * sb.Append(comment); * sb.Append(tab0).Append(MemberDeclaration(ctor, preventVis)).Append(semi).Append(nl); * return sb.ToString(); * } * }*/ // CLASS sb.Append(CommentDeclaration(Comments, tab0)).Append(tab0); if (!caching && InFile.Version != 3 && (this.Flags & (FlagType.Intrinsic | FlagType.Interface)) == 0) { sb.Append((InFile.haXe) ? "extern " : "intrinsic "); } sb.Append(ClassDeclaration(this, InFile.Version < 3)); if (ExtendsType != null) { if ((this.Flags & FlagType.Abstract) > 0) { sb.Append(" from ").Append(ExtendsType); } else { sb.Append(" extends ").Append(ExtendsType); } } if (Implements != null) { sb.Append(" implements "); bool addSep = false; foreach (string iname in Implements) { if (addSep) { sb.Append(", "); } else { addSep = true; } sb.Append(iname); } } sb.Append(nl).Append(tab0).Append('{'); // MEMBERS int count = 0; foreach (MemberModel var in Members) { if ((var.Flags & FlagType.Variable) > 0) { ASMetaData.GenerateIntrinsic(var.MetaDatas, sb, nl, tab); String comment = CommentDeclaration(var.Comments, tab); if (count == 0 || comment != "") { sb.Append(nl); } sb.Append(comment); sb.Append(tab).Append(MemberDeclaration(var, preventVis)).Append(semi).Append(nl); count++; } } // MEMBERS string decl; MemberModel temp; string prevProperty = null; foreach (MemberModel property in Members) { if ((property.Flags & (FlagType.Getter | FlagType.Setter)) > 0) { if (prevProperty != property.Name) { sb.Append(nl); } prevProperty = property.Name; ASMetaData.GenerateIntrinsic(property.MetaDatas, sb, nl, tab); sb.Append(CommentDeclaration(property.Comments, tab)); FlagType flags = (property.Flags & ~(FlagType.Setter | FlagType.Getter)) | FlagType.Function; if ((property.Flags & FlagType.Getter) > 0) { temp = (MemberModel)property.Clone(); temp.Name = "get " + temp.Name; temp.Flags = flags; temp.Parameters = null; string memberDecl = MemberDeclaration(temp, preventVis); // Typed callback declaration (in get property) if ((property.Flags & FlagType.Function) > 0) { string commentDecl = property.ToDeclarationString(); int idxA = Math.Max(memberDecl.LastIndexOf(":"), memberDecl.LastIndexOf(")") + 1); int idxB = Math.Min(commentDecl.IndexOf(":"), commentDecl.IndexOf("/*")); if (idxA > 0 && idxB > -1) { memberDecl = memberDecl.Substring(0, idxA) + commentDecl.Substring(idxB); } } sb.Append(tab).Append(memberDecl).Append(semi).Append(nl); } if ((property.Flags & FlagType.Setter) > 0) { temp = (MemberModel)property.Clone(); temp.Name = "set " + temp.Name; temp.Flags = flags; temp.Type = (InFile.Version == 3) ? "void" : "Void"; sb.Append(tab).Append(MemberDeclaration(temp, preventVis)).Append(semi).Append(nl); } } } // MEMBERS foreach (MemberModel method in Members) { if ((method.Flags & FlagType.Function) > 0 && (method.Flags & FlagType.Variable) == 0 && (method.Flags & FlagType.Getter) == 0) { decl = MemberDeclaration(method, preventVis); if (InFile.haXe && (method.Flags & FlagType.Constructor) > 0) { decl = decl.Replace("function " + method.Name, "function new"); } ASMetaData.GenerateIntrinsic(method.MetaDatas, sb, nl, tab); sb.Append(nl).Append(CommentDeclaration(method.Comments, tab)); sb.Append(tab).Append(decl).Append(semi).Append(nl); } } // END CLASS sb.Append(tab0).Append('}'); return(sb.ToString()); }
private void ReadStyleMeta(ASDocItem doc) { if (IsEmptyElement || !HasAttributes) return; ASMetaData meta = new ASMetaData("Style"); meta.Kind = ASMetaKind.Style; meta.Comments = ""; string sName = GetAttribute("name"); string sType = GetAttribute("type"); //string sInherit = GetAttribute("inherit"); //string sFormat = GetAttribute("format"); string sEnum = GetAttribute("enumeration"); string sDefault = null; string eon = Name; ReadStartElement(); while (Name != eon) { if (NodeType == XmlNodeType.Element) switch (Name) { case "description": meta.Comments = ReadValue() ?? ""; break; case "default": sDefault = ReadValue(); break; } Read(); } if (doc.Meta == null) doc.Meta = new List<ASMetaData>(); if (sDefault != null) meta.Comments = meta.Comments.Trim() + "\n@default\t" + sDefault; meta.Params = new Dictionary<string, string>(); meta.Params["name"] = sName; meta.Params["type"] = sType; meta.RawParams = String.Format("name=\"{0}\", type=\"{1}\"", sName, sType); if (sEnum != null) { meta.Params["enumeration"] = sEnum; meta.RawParams += ", enumeration=\"" + sEnum + "\""; } doc.Meta.Add(meta); }
//--------------------------- // Meta tags //--------------------------- private void ReadExcludeMeta(ASDocItem doc) { if (!HasAttributes) return; ASMetaData meta = new ASMetaData("Style"); meta.Kind = ASMetaKind.Exclude; string sKind = GetAttribute("kind"); string sName = GetAttribute("name"); if (doc.Meta == null) doc.Meta = new List<ASMetaData>(); meta.Params = new Dictionary<string, string>(); meta.Params["kind"] = sKind; meta.Params["name"] = sName; meta.RawParams = String.Format("kind=\"{0}\", name=\"{1}\"", sKind, sName); doc.Meta.Add(meta); }
public string GenerateIntrinsic(bool caching) { if (this == Ignore) { return(""); } StringBuilder sb = new StringBuilder(); string nl = (caching) ? "" : "\r\n"; char semi = ';'; string tab = (caching) ? "" : "\t"; // header if (Version > 2) { sb.Append("package"); if (Package.Length > 0) { sb.Append(" ").Append(Package); } if (haXe) { sb.Append(semi).Append(nl).Append(nl); } else { sb.Append(nl).Append("{").Append(nl); } } // imports if (Imports.Count > 0) { foreach (MemberModel import in Imports) { sb.Append(tab).Append("import ").Append(import.Type).Append(semi).Append(nl); } sb.Append(nl); } // event/style metadatas ASMetaData.GenerateIntrinsic(MetaDatas, sb, nl, tab); // members string decl; foreach (MemberModel member in Members) { ASMetaData.GenerateIntrinsic(member.MetaDatas, sb, nl, tab); if ((member.Flags & FlagType.Variable) > 0) { sb.Append(ClassModel.CommentDeclaration(member.Comments, tab)); sb.Append(tab).Append(ClassModel.MemberDeclaration(member)).Append(semi).Append(nl); } else if ((member.Flags & FlagType.Function) > 0) { decl = ClassModel.MemberDeclaration(member); sb.Append(ClassModel.CommentDeclaration(member.Comments, tab)); sb.Append(tab).Append(decl).Append(semi).Append(nl); } } foreach (ClassModel aClass in Classes) { sb.Append(aClass.GenerateIntrinsic(caching)); sb.Append(nl); } if (Version == 3) { sb.Append('}').Append(nl); } return(sb.ToString()); }
private static MemberModel GetMember(MemberInfo info, FlagType baseFlags) { MemberModel member = new MemberModel(); member.Name = info.name.localName; member.Flags = baseFlags; member.Access = Visibility.Public; member.Namespace = "public"; if (info.metadata != null && info.metadata.Count > 0) { var metadatas = member.MetaDatas; foreach (var metaInfo in info.metadata) { if (metaInfo.name == "__go_to_definition_help") continue; var meta = new ASMetaData(metaInfo.name); var rawParams = new StringBuilder(); meta.Params = new Dictionary<string, string>(metaInfo.Count); foreach (var entry in metaInfo) { if (entry.Length != 2) continue; meta.Params[entry[0]] = entry[1]; if (rawParams.Length > 0) rawParams.Append(","); rawParams.Append(entry[0] + "=\"" + entry[1] + "\""); } meta.RawParams = rawParams.ToString(); if (metadatas == null) metadatas = new List<ASMetaData>(info.metadata.Count); metadatas.Add(meta); } member.MetaDatas = metadatas; } if (info is SlotInfo) { SlotInfo slot = info as SlotInfo; member.Flags |= FlagType.Variable; if (slot.kind == TraitMember.Const) member.Flags |= FlagType.Constant; if (slot.value is Namespace) { member.Flags |= FlagType.Namespace; member.Value = '"' + (slot.value as Namespace).uri + '"'; } member.Type = ImportType(slot.type); } else if (info is MethodInfo) { switch (info.kind) { case TraitMember.Setter: member.Flags |= FlagType.Setter; break; case TraitMember.Getter: member.Flags |= FlagType.Getter; break; default: member.Flags |= FlagType.Function; break; } MethodInfo method = info as MethodInfo; QName type = method.returnType; member.Type = ImportType(type); member.Parameters = new List<MemberModel>(); int n = method.paramTypes.Length; int defaultValues = (method.optionalValues != null) ? n - method.optionalValues.Length : n; for (int i = 0; i < n; i++) { MemberModel param = new MemberModel(); param.Flags = FlagType.ParameterVar | FlagType.Variable; param.Name = (!inSWF && method.paramNames != null) ? method.paramNames[i] : "param" + i; type = method.paramTypes[i]; param.Type = ImportType(type); if (param.Name[0] == '.' && param.Type == "Array") // ...rest { param.Type = ""; } else if (i >= defaultValues) { SetDefaultValue(param, method.optionalValues[i - defaultValues]); } member.Parameters.Add(param); } } else { member = null; } return member; }
private void ReadPrologMetadataDefaultProperty(ASDocItem doc) { ASMetaData meta = new ASMetaData("DefaultProperty"); meta.Kind = ASMetaKind.DefaultProperty; meta.Comments = ""; meta.Params = new Dictionary<string, string>(); string defValue = GetAttribute("name"); meta.Params["default"] = defValue; meta.RawParams = string.Format("\"{0}\"", defValue); if (doc.Meta == null) doc.Meta = new List<ASMetaData>(); doc.Meta.Add(meta); }