Ejemplo n.º 1
0
        // This method is called after the string has been committed to the source buffer.
        /// <summary>
        /// Called after the declaration has been committed to the source file. When implemented in a derived class, it provides a completion character which may itself be a trigger for another round of IntelliSense.
        /// </summary>
        /// <param name="textView">[in] An <see cref="T:Microsoft.VisualStudio.TextManager.Interop.IVsTextView"/> object representing the view that displays the source file.</param>
        /// <param name="committedText">[in] A string containing the text that was inserted as part of the completion process.</param>
        /// <param name="commitCharacter">[in] The character that was used to commit the text to the source file.</param>
        /// <param name="index">[in] The index of the item that was committed to the source file.</param>
        /// <returns>
        /// Returns a character to be inserted after the committed text. If nothing is to be inserted, returns 0.
        /// </returns>
        public override char OnAutoComplete(IVsTextView textView,
                                            string committedText,
                                            char commitCharacter,
                                            int index)
        {
/*
 *          // Do not replace when committed with \13 (enter)
 *          if (commitCharacter == 13)
 *              return '\0';
 */
            if (index < 0)
            {
                return('\0');
            }
            Declaration declaration = declarations[index];

            if (declaration != null)
            {
                // In this example, MyDeclaration identifies types with a string.
                // You can choose a different approach.
                if (declaration.DeclarationType == DeclarationType.Snippet)
                {
                    Source source = languageService.GetSource(textView);
                    if (source != null)
                    {
                        ExpansionProvider expansionProvider = source.GetExpansionProvider();
                        if (expansionProvider != null)
                        {
                            string title;
                            string path;
                            int    commitLength = commitSpan.iEndIndex - commitSpan.iStartIndex;
                            if (commitLength < committedText.Length)
                            {
                                // Replace everything that was inserted
                                // so calculate the span of the full
                                // insertion, taking into account what
                                // was inserted when the commitSpan
                                // was obtained in the first place.
                                commitSpan.iEndIndex += (committedText.Length - commitLength);
                            }

                            if (expansionProvider.FindExpansionByShortcut(textView,
                                                                          committedText,
                                                                          commitSpan,
                                                                          true,
                                                                          out title,
                                                                          out path) == 0)
                            {
                                expansionProvider.InsertNamedExpansion(textView,
                                                                       title,
                                                                       path,
                                                                       commitSpan,
                                                                       false);
                            }
                        }
                    }
                }
            }
            return('\0');
        }
        public override bool OnSynchronizeDropdowns(
            Microsoft.VisualStudio.Package.LanguageService languageService,
            IVsTextView textView,
            int line,
            int col,
            ArrayList dropDownTypes,
            ArrayList dropDownMembers,
            ref int selectedType,
            ref int selectedMember)
        {
            //
            var package         = XSharp.Project.XSharpProjectPackage.Instance;
            var optionsPage     = package.GetIntellisenseOptionsPage();
            var sortItems       = optionsPage.SortNavigationBars;
            var includeFields   = optionsPage.IncludeFieldsInNavigationBars;
            var currentTypeOnly = optionsPage.ShowMembersOfCurrentTypeOnly;

            if (optionsPage.DisableEditorDropdowns)
            {
                dropDownTypes.Clear();
                dropDownMembers.Clear();
                selectedType = selectedMember = -1;
                return(true);
            }
            // when the line did not change, we do nothing for performance reasons
            // this speeds up typing  for buffers with lots of entities
            if (line == lastLine)
            {
                // same line, no changes
                return(false);
            }
            lastLine = line;

            Source src     = languageService.GetSource(textView);
            string srcFile = src.GetFilePath();
            //
            XFile file = XSolution.FindFullPath(srcFile);

            if (file == null || file.TypeList == null)
            {
                return(false);
            }
            XElement selectedElement = file.FindMemberAtRow(line);

            if (selectedElement == _lastSelected)
            {
                // Same element, no changes
                return(false);
            }
            // check if we are on the same type. When not then we need to reload the members.
            // Note that the first item in the members combo can also be a type (Classname)
            XElement parentType = null;

            if (selectedElement is XTypeMember)
            {
                parentType = selectedElement.Parent;
            }
            else if (selectedElement is XType)
            {
                parentType = selectedElement as XType;
            }
            bool newType = true;

            if (parentType != null && _lastType != null && parentType.FullName == _lastType.FullName)
            {
                newType = false;
            }
            // when we are on the same type and there are no new methods then we can
            // select the element in the members combo and we do not have to rebuild the members
            // list. We must set the selectedType and selectedMember
            if (!newType && file.ContentHashCode == _lastHashCode && lastIncludeFields == includeFields && lastCurrentTypeOnly == currentTypeOnly)
            {
                // no need to rebuild the list. Just focus to another element
                // locate item in members collection
                selectedMember = -1;
                selectedType   = -1;
                for (int i = 0; i < dropDownMembers.Count; i++)
                {
                    var member = (XDropDownMember)dropDownMembers[i];
                    if (member.Element.ComboPrototype == selectedElement.ComboPrototype)
                    {
                        selectedMember = i;
                        break;
                    }
                }
                // find the parentType in the types combo
                if (selectedMember != -1 && parentType != null) // should never be null
                {
                    for (int i = 0; i < dropDownTypes.Count; i++)
                    {
                        var member = (XDropDownMember)dropDownTypes[i];
                        var type   = member.Element as XType;
                        if (type.FullName == parentType.FullName)
                        {
                            selectedType = i;
                            break;
                        }
                    }
                }
                // normally we should always find it. But if it fails then we simply build the list below.
                if (selectedMember != -1 && selectedType != -1)
                {
                    // remember for later. No need to remember the type because it has not changed
                    _lastSelected = selectedElement;
                    return(true);
                }
            }
            dropDownTypes.Clear();
            dropDownMembers.Clear();
            int nSelType = -1;
            int nSelMbr  = -1;
            //int distanceM = int.MaxValue;
            DROPDOWNFONTATTR ft;

            //
            //
            if (file.TypeList.Count > 0)
            {
                nSelType = 0;
            }

            List <XType> xList = file.TypeList.Values.ToList <XType>();

            if (sortItems)
            {
                xList.Sort(delegate(XType elt1, XType elt2)
                {
                    return(elt1.Name.CompareTo(elt2.Name));
                });
            }
            XType typeGlobal = null;
            int   nSelect    = 0;

            XElement currentMember = null;
            XType    currentType   = null;

            if (selectedElement is XTypeMember)
            {
                currentMember = selectedElement as XTypeMember;
                currentType   = ((XTypeMember)currentMember).Parent;
            }
            else if (selectedElement is XType)
            {
                currentType   = selectedElement as XType;
                currentMember = null;
            }
            nSelect = 0;
            XDropDownMember elt;

            // C# shows all items PLAIN
            // but when the selection is not really on an item, but for example on a comment
            // between methods, or on the comments between the namespace and the first class
            // then the next method/class is selected and displayed in GRAY
            // C# also includes members (for partial classes) that are defined in other source files
            // these are colored GRAY
            foreach (XType eltType in xList)
            {
                if (eltType.Kind == Kind.Namespace)
                {
                    continue;
                }
                //
                if (XType.IsGlobalType(eltType))
                {
                    typeGlobal = eltType;
                }
                TextSpan sp = this.TextRangeToTextSpan(eltType.Range);
                ft = DROPDOWNFONTATTR.FONTATTR_PLAIN;
                string name = eltType.Name;
                if (string.IsNullOrEmpty(name))
                {
                    name = "?";
                }
                elt         = new XDropDownMember(name, sp, eltType.Glyph, ft);
                elt.Element = eltType;
                nSelect     = dropDownTypes.Add(elt);
                if (eltType?.FullName == currentType?.FullName)
                {
                    nSelType = nSelect;
                }
            }

            if (currentType == null)
            {
                currentType = typeGlobal;
            }
            bool hasPartial = false;

            if (currentType != null)    // should not happen since all files have a global type
            {
                nSelMbr = 0;
                var members = new List <XElement>();
                if (currentTypeOnly)
                {
                    if (currentType != typeGlobal && currentType.IsPartial)
                    {
                        // retrieve members from other files ?
                        var fullType = file.Project.Lookup(currentType.FullName, true);
                        hasPartial = true;
                        members.AddRange(fullType.Members);
                    }
                    else
                    {
                        members.AddRange(currentType.Members);
                    }
                }
                else
                {
                    members.AddRange(file.EntityList.Where(member => includeFields || (member.Kind != Kind.Field && member.Kind != Kind.VODefine)));
                    foreach (var ent in file.EntityList)
                    {
                        if (ent is XType)
                        {
                            var xType = ent as XType;
                            if (xType.IsPartial)
                            {
                                // load methods from other files
                                var fullType = file.Project.Lookup(xType.FullName, true);
                                hasPartial = true;
                                foreach (var member in fullType.Members)
                                {
                                    if (!members.Contains(member))
                                    {
                                        if (includeFields || (member.Kind != Kind.Field && member.Kind != Kind.VODefine))
                                        {
                                            members.Add(member);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if (sortItems)
                {
                    members = members.OrderBy(x => x.FullName).ToList();
                }
                // Add member for class declaration. This also makes sure that there at least one
                // element in the members list, which is convenient.
                TextSpan spM = this.TextRangeToTextSpan(currentType.Range);
                ft = DROPDOWNFONTATTR.FONTATTR_PLAIN;
                if (currentTypeOnly)
                {
                    // Add a 'root' element for the type.
                    if (currentType != typeGlobal)
                    {
                        if (currentType.Kind != Kind.Delegate)
                        {
                            elt         = new XDropDownMember("(" + currentType.Name + ")", spM, currentType.Glyph, ft);
                            elt.Element = currentType;
                            dropDownMembers.Add(elt);
                        }
                    }
                    else
                    {
                        elt         = new XDropDownMember(currentType.Name, spM, currentType.Glyph, ft);
                        elt.Element = currentType;
                        dropDownMembers.Add(elt);
                    }
                }
                foreach (XElement member in members)
                {
                    bool otherFile;
                    if (includeFields || (member.Kind != Kind.Field && member.Kind != Kind.VODefine))
                    {
                        spM       = this.TextRangeToTextSpan(member.Range);
                        otherFile = false;
                        ft        = DROPDOWNFONTATTR.FONTATTR_PLAIN;
                        if (hasPartial)
                        {
                            otherFile = member.File != file;
                        }

                        string prototype = member.ComboPrototype;
                        if (!currentTypeOnly && member.Parent != null && member.Parent != typeGlobal)
                        {
                            if (member.Modifiers.HasFlag(Modifiers.Static))
                            {
                                prototype = member.Parent.Name + "." + prototype;
                            }
                            else
                            {
                                prototype = member.Parent.Name + ":" + prototype;
                            }
                        }

                        if (otherFile)
                        {
                            ft         = DROPDOWNFONTATTR.FONTATTR_GRAY;
                            prototype += " (" + System.IO.Path.GetFileName(member.File.SourcePath) + ")";
                        }
                        elt         = new XDropDownMember(prototype, spM, member.Glyph, ft);
                        nSelect     = dropDownMembers.Add(elt);
                        elt.Element = member;
                        if (member == currentMember)
                        {
                            nSelMbr = nSelect;
                        }
                    }
                }
            }
            // save the info so we can optimize the next call.
            _members            = dropDownMembers;
            _file               = file;
            _lastSelected       = selectedElement;
            _lastType           = currentType;
            _lastHashCode       = file.ContentHashCode;
            selectedType        = nSelType;
            selectedMember      = nSelMbr;
            lastIncludeFields   = includeFields;
            lastCurrentTypeOnly = currentTypeOnly;
            return(true);
        }
Ejemplo n.º 3
0
        /// <include file='doc\Source.uex' path='docs/doc[@for="Completor.Completor"]/*' />
        public Completor(LanguageService langsvc, IVsTextView view, string description)
        {
            this.langsvc = langsvc;
            this.view = view;
            this.src = langsvc.GetSource(view);
            this.sb = new StringBuilder();
            this.caret = 0; // current position within StringBuilder.
            this.ca = CompoundActionFactory.GetCompoundAction(null, this.src, description);
            this.ca.FlushEditActions(); // make sure we see a consistent coordinate system.
            // initialize span representing what we are removing from the buffer.
            NativeMethods.ThrowOnFailure(view.GetCaretPos(out span.iStartLine, out span.iStartIndex));
            this.span.iEndLine = span.iStartLine;
            this.span.iEndIndex = span.iStartIndex;
            RefreshLine();

            macro = this.langsvc.GetIVsTextMacroHelperIfRecordingOn();
        }