상속: CompletionData, IActionCompletionData
        void AddVirtuals(CodeCompletionContext ctx, Dictionary<string, bool> alreadyInserted, CompletionDataList completionList, IType type, string modifiers, IReturnType curType)
        {
            if (curType == null)
                return;
            IType searchType = dom.SearchType (new SearchTypeRequest (Document.CompilationUnit, curType, type));
            //System.Console.WriteLine("Add Virtuals for:" + searchType + " / " + curType);
            if (searchType == null)
                return;
            bool isInterface      = type.ClassType == ClassType.Interface;
            bool includeOverriden = false;

            int declarationBegin = ctx.TriggerOffset;
            int j = declarationBegin;
            for (int i = 0; i < 3; i++) {
                switch (GetPreviousToken (ref j, true)) {
                    case "public":
                    case "protected":
                    case "private":
                    case "internal":
                    case "sealed":
                    case "override":
                        declarationBegin = j;
                        break;
                    case "static":
                        return; // don't add override completion for static members
                }
            }
            foreach (IType t in this.dom.GetInheritanceTree (searchType)) {
                //System.Console.WriteLine("t:" + t);
                foreach (IMember m in t.Members) {
                    if (!m.IsAccessibleFrom (dom, type, type, true) || m.IsSpecialName)
                        continue;
                    //System.Console.WriteLine ("scan:" + m);
                    //if (m.IsSpecialName || (m.IsInternal && !m.IsProtectedOrInternal) || && searchType.SourceProject != Document.Project)
                    //	continue;
                    if (t.ClassType == ClassType.Interface || (isInterface || m.IsVirtual || m.IsAbstract) && !m.IsSealed && (includeOverriden || !type.HasOverriden (m))) {
                        // filter out the "Finalize" methods, because finalizers should be done with destructors.
                        if (m is IMethod && m.Name == "Finalize")
                            continue;

                        //System.Console.WriteLine("add");
                        NewOverrideCompletionData data = new NewOverrideCompletionData (dom, Editor, declarationBegin, type, m);
                        string text = CompletionDataCollector.ambience.GetString (m, OutputFlags.ClassBrowserEntries);
                        // check if the member is already implemented
                        bool foundMember = false;
                        foreach (IMember member in type.Members) {
                            if (text == CompletionDataCollector.ambience.GetString (member, OutputFlags.ClassBrowserEntries)) {
                                foundMember = true;
                                break;
                            }
                        }

                        if (!foundMember && !alreadyInserted.ContainsKey (text)) {
                            alreadyInserted[text] = true;
                            completionList.Add (data);
                        }
                    }
                }
            }
        }
        CompletionDataList GetPartialCompletionData(CodeCompletionContext ctx, IType type, string modifiers)
        {
            CompletionDataList result = new ProjectDomCompletionDataList ();

            CompoundType partialType = dom.GetType (type.FullName) as CompoundType;
            if (partialType != null) {
                List<IMethod> methods = new List<IMethod> ();
                // gather all partial methods without implementation
                foreach (IType part in partialType.Parts) {
                    if (part.Location == type.Location && part.CompilationUnit.FileName == type.CompilationUnit.FileName)
                        continue;
                    foreach (IMethod method in part.Methods) {
                        if (method.IsPartial && method.BodyRegion.End.Line == 0 && !ContainsDeclaration (type, method)) {
                            methods.Add (method);
                        }
                    }
                }

                // now filter all methods that are implemented in the compound class
                foreach (IType part in partialType.Parts) {
                    if (part.Location == type.Location && part.CompilationUnit.FileName == type.CompilationUnit.FileName)
                        continue;
                    for (int i = 0; i < methods.Count; i++) {
                        IMethod curMethod = methods[i];
                        IMethod method = GetDeclaration (part, curMethod);
                        if (method != null && method.BodyRegion.End.Line != 0) {
                            methods.RemoveAt (i);
                            i--;
                            continue;
                        }
                    }
                }

                foreach (IMethod method in methods) {
                    NewOverrideCompletionData data = new NewOverrideCompletionData (dom, Editor, ctx.TriggerOffset, type, method);
                    data.GenerateBody = false;
                    result.Add (data);
                }

            }
            return result;
        }