/// <summary>
        /// Extract documentation from XML included in ASDocs-enriched SWCs
        /// </summary>
        /// <param name="rawDocs"></param>
        private static void ParseDocumentation(ContentParser parser)
        {
            if (parser.Catalog != null)
            {
                MxmlFilter.AddCatalog(parser.Filename, parser.Catalog);
            }

            if (parser.Docs.Count > 0)
                foreach (string docFile in parser.Docs.Keys)
                {
                    if (docFile.EndsWith(".dita.xml"))
                        continue;
                    try
                    {
                        Match m = reDocFile.Match(docFile);
                        if (!m.Success) continue;
                        string package = m.Groups[1].Value;
                        Dictionary<string, ASDocItem> packageDocs = Docs.ContainsKey(package)
                            ? Docs[package]
                            : new Dictionary<string, ASDocItem>();

                        byte[] rawDoc = parser.Docs[docFile];
                        ASDocsReader dr = new ASDocsReader(rawDoc);
                        dr.ExcludedASDocs = ExcludedASDocs;
                        dr.Parse(packageDocs);

                        Docs[package] = packageDocs;
                    }
                    catch (Exception)
                    {
                    }
                }
        }
        /// <summary>
        /// Create virtual FileModel objects from Abc bytecode
        /// </summary>
        /// <param name="abcs"></param>
        /// <param name="path"></param>
        /// <param name="context"></param>
        public static void Convert(ContentParser parser, PathModel path, IASContext context)
        {
            inSWF = Path.GetExtension(path.Path).ToLower() == ".swf";

            // extract documentation
            ParseDocumentation(parser);

            // extract models
            Dictionary<string, FileModel> models = new Dictionary<string, FileModel>();
            FileModel privateClasses = new FileModel(Path.Combine(path.Path, "__Private.as"));
            privateClasses.Version = 3;
            privateClasses.Package = "private";
            genericTypes = new Dictionary<string, FileModel>();
            imports = new Dictionary<string, string>();
            conflicts = new Dictionary<string, string>();

            foreach (Abc abc in parser.Abcs)
            {
                // types
                foreach (Traits trait in abc.classes)
                {
                    Traits instance = trait.itraits;
                    if (instance == null)
                        continue;
                    imports.Clear();
                    conflicts.Clear();

                    FileModel model = new FileModel("");
                    model.Context = context;
                    model.Package = reSafeChars.Replace(instance.name.uri, "_");
                    model.HasPackage = true;
                    string filename = reSafeChars.Replace(trait.name.ToString(), "_").TrimEnd('$');
                    filename = Path.Combine(model.Package.Replace('.', Path.DirectorySeparatorChar), filename);
                    model.FileName = Path.Combine(path.Path, filename);
                    model.Version = 3;

                    ClassModel type = new ClassModel();
                    model.Classes = new List<ClassModel>();
                    model.Classes.Add(type);

                    type.InFile = model;
                    type.Type = instance.name.ToTypeString();
                    type.Name = instance.name.localName;
                    type.Flags = FlagType.Class;
                    conflicts.Add(type.Name, type.QualifiedName);

                    if (instance.flags == TraitMember.Function)
                        type.Flags |= FlagType.Interface;

                    thisDocs = GetDocs(model.Package);
                    if (thisDocs != null)
                    {
                        docPath = (model.Package.Length > 0 ? model.Package + ":" : "globalClassifier:") + type.Name;
                        if (thisDocs.ContainsKey(docPath))
                        {
                            ASDocItem doc = thisDocs[docPath];
                            applyASDoc(doc, type);
                            if (doc.Meta != null) model.MetaDatas = doc.Meta;
                        }
                        if (model.Package.Length == 0) docPath = type.Name;
                    }

                    if (instance.baseName.uri == model.Package)
                        type.ExtendsType = ImportType(instance.baseName.localName);
                    else type.ExtendsType = ImportType(instance.baseName);

                    if (instance.interfaces != null && instance.interfaces.Length > 0)
                    {
                        type.Implements = new List<string>();
                        foreach (QName name in instance.interfaces)
                            type.Implements.Add(ImportType(name));
                    }

                    if (model.Package == "private")
                    {
                        model.Package = "";
                        type.Access = Visibility.Private;
                        type.Namespace = "private";
                    }
                    else if (model.Package == "__AS3__.vec")
                    {
                        model.Package = "";
                        type.Access = Visibility.Private;
                        type.Namespace = "private";
                        string genType = type.Name;
                        if (type.Name.IndexOf("$") > 0)
                        {
                            string[] itype = type.Name.Split('$');
                            genType = itype[0];
                            type.Name = itype[0] + "$" + itype[1];
                            type.IndexType = itype[1];
                        }
                        if (genericTypes.ContainsKey(genType))
                        {
                            model.Classes.Clear();
                            type.InFile = genericTypes[genType];
                            genericTypes[genType].Classes.Add(type);
                        }
                        else genericTypes[genType] = model;
                    }
                    else if (type.Name.StartsWith("_"))
                    {
                        type.Access = Visibility.Private;
                        type.Namespace = "private";
                    }
                    else
                    {
                        type.Access = Visibility.Public;
                        type.Namespace = "public";
                    }

                    type.Members = GetMembers(trait.members, FlagType.Static, instance.name);
                    type.Members.Add(GetMembers(instance.members, FlagType.Dynamic, instance.name));

                    if ((type.Flags & FlagType.Interface) > 0)
                    {
                        // TODO properly support interface multiple inheritance
                        type.ExtendsType = null;
                        if (type.Implements != null && type.Implements.Count > 0)
                        {
                            type.ExtendsType = type.Implements[0];
                            type.Implements.RemoveAt(0);
                            if (type.Implements.Count == 0) type.Implements = null;
                        }

                        foreach (MemberModel member in type.Members)
                        {
                            member.Access = Visibility.Public;
                            member.Namespace = "";
                        }
                    }

                    // constructor
                    if (instance.init != null && (type.Flags & FlagType.Interface) == 0)
                    {
                        List<MemberInfo> temp = new List<MemberInfo>(new MemberInfo[] { instance.init });
                        MemberList result = GetMembers(temp, 0, instance.name);
                        if (result.Count > 0)
                        {
                            MemberModel ctor = result[0];
                            ctor.Flags |= FlagType.Constructor;
                            ctor.Access = Visibility.Public;
                            ctor.Type = type.Type;
                            ctor.Namespace = "public";
                            type.Members.Merge(result);
                            type.Constructor = ctor.Name;
                        }
                        result = null;
                        temp = null;
                    }
                    else type.Constructor = type.Name;

                    if (type.Access == Visibility.Private)
                    {
                        model = privateClasses;
                        type.InFile = model;
                    }

                    if (model.Classes.Count > 0 || model.Members.Count > 0)
                    {
                        AddImports(model, imports);
                        models[model.FileName] = model;
                    }
                }

                // packages
                if (abc.scripts == null)
                    continue;
                foreach (Traits trait in abc.scripts)
                {
                    FileModel model = null;
                    foreach (MemberInfo info in trait.members)
                    {
                        if (info.kind == TraitMember.Class)
                            continue;

                        MemberModel member = GetMember(info, 0);
                        if (member == null) continue;

                        if (model == null || model.Package != info.name.uri)
                        {
                            AddImports(model, imports);

                            string package = info.name.uri ?? "";
                            string filename = package.Length > 0 ? "package.as" : "toplevel.as";
                            filename = Path.Combine(package.Replace('.', Path.DirectorySeparatorChar), filename);
                            filename = Path.Combine(path.Path, filename);
                            if (models.ContainsKey(filename))
                                model = models[filename];
                            else
                            {
                                model = new FileModel("");
                                model.Context = context;
                                model.Package = package;
                                model.HasPackage = true;
                                model.FileName = filename;
                                model.Version = 3;
                                models[filename] = model;
                            }
                        }

                        thisDocs = GetDocs(model.Package);
                        if (thisDocs != null)
                        {
                            docPath = "globalOperation:" + (model.Package.Length > 0 ? model.Package + ":" : "")
                                + member.Name;
                            if (member.Access == Visibility.Public && !String.IsNullOrEmpty(member.Namespace)
                                && member.Namespace != "public")
                                docPath += member.Namespace + ":";
                            if ((member.Flags & FlagType.Setter) > 0) docPath += ":set";
                            else if ((member.Flags & FlagType.Getter) > 0) docPath += ":get";

                            if (thisDocs.ContainsKey(docPath)) applyASDoc(thisDocs[docPath], member);
                        }

                        member.InFile = model;
                        member.IsPackageLevel = true;
                        model.Members.Add(member);
                    }

                    AddImports(model, imports);
                }
            }

            if (privateClasses.Classes.Count > 0) models[privateClasses.FileName] = privateClasses;

            // some SWCs need manual fixes
            CustomFixes(path.Path, models);

            // fake SWC (like 'playerglobal_rb.swc', only provides documentation)
            if (models.Keys.Count == 1)
            {
                foreach (FileModel model in models.Values)
                    if (model.GetPublicClass().QualifiedName == "Empty")
                    {
                        models.Clear();
                        break;
                    }
            }

            path.SetFiles(models);
        }
        private bool OpenVirtualFileModel(string virtualPath)
        {
            int p = virtualPath.IndexOf("::");
            if (p < 0) return false;

            string container = virtualPath.Substring(0, p);
            string ext = Path.GetExtension(container).ToLower();
            if (ext != ".swf" && ext != ".swc" && ext != ".ane") return false;
            if (!File.Exists(container)) return false;

            string fileName = Path.Combine(container, virtualPath.Substring(p + 2).Replace('.', Path.DirectorySeparatorChar));
            PathModel path = new PathModel(container, contextInstance);
            ContentParser parser = new ContentParser(path.Path);
            parser.Run();
            AbcConverter.Convert(parser, path, contextInstance);

            if (path.HasFile(fileName))
            {
                FileModel model = path.GetFile(fileName);
                ASComplete.OpenVirtualFile(model);
                return true;
            }
            int split = fileName.LastIndexOf(Path.DirectorySeparatorChar) + 1;
            fileName = fileName.Substring(0, split) + "package.as";
            if (path.HasFile(fileName))
            {
                FileModel model = path.GetFile(fileName);
                ASComplete.OpenVirtualFile(model);
                return true;
            }
            fileName = fileName.Substring(0, split) + "toplevel.as";
            if (path.HasFile(fileName))
            {
                FileModel model = path.GetFile(fileName);
                ASComplete.OpenVirtualFile(model);
                return true;
            }
            return false;
        }
Exemple #4
0
        /// <summary>
        /// Parse a packaged library file
        /// </summary>
        /// <param name="path">Models owner</param>
        public override void ExploreVirtualPath(PathModel path)
        {
            if (path.WasExplored)
            {
                if (MxmlFilter.HasCatalog(path.Path)) MxmlFilter.AddCatalog(path.Path);

                if (path.FilesCount != 0) // already parsed
                    return;
            }

            try
            {
                if (File.Exists(path.Path) && !path.WasExplored)
                {
                    bool isRefresh = path.FilesCount > 0;
                    //TraceManager.AddAsync("parse " + path.Path);
                    lock (path)
                    {
                        path.WasExplored = true;
                        ContentParser parser = new ContentParser(path.Path);
                        parser.Run();
                        AbcConverter.Convert(parser, path, this);
                    }
                    // reset FCSH
                    if (isRefresh)
                    {
                        EventManager.DispatchEvent(this,
                            new DataEvent(EventType.Command, "ProjectManager.RestartFlexShell", path.Path));
                    }
                }
            }
            catch (Exception ex)
            {
                string message = TextHelper.GetString("Info.ExceptionWhileParsing");
                TraceManager.AddAsync(message + " " + path.Path);
                TraceManager.AddAsync(ex.Message);
                TraceManager.AddAsync(ex.StackTrace);
            }
        }