Esempio n. 1
0
        protected override CompletionDataList GetAttributeValueCompletions(S.IAttributedXObject ob, S.XAttribute att)
        {
            var list = base.GetAttributeValueCompletions(ob, att) ?? new CompletionDataList();

            if (ob is S.XElement)
            {
                if (ob.Name.HasPrefix)
                {
                    S.XAttribute idAtt = ob.Attributes[new S.XName("id")];
                    string       id    = idAtt == null? null : idAtt.Value;
                    if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(id.Trim()))
                    {
                        id = null;
                    }
                    AddAspAttributeValueCompletionData(list, ob.Name, att.Name, id);
                }
            }
            else if (ob is AspNetDirective)
            {
                return(DirectiveCompletion.GetAttributeValues(project, Document.FileName, ob.Name.FullName, att.Name.FullName));
            }
            return(list.Count > 0? list : null);
        }
Esempio n. 2
0
 protected virtual void AddAttributeValueCompletionData(CodeCompletionDataProvider cp, S.XElement element, S.XAttribute attribute)
 {
 }
Esempio n. 3
0
        ICompletionDataProvider HandleCodeCompletion(
            CodeCompletionContext completionContext, bool forced, ref int triggerWordLength)
        {
            tracker.UpdateEngine();

            //FIXME: lines in completionContext are zero-indexed, but ILocation and buffer are 1-indexed.
            //This could easily cause bugs.
            int line = completionContext.TriggerLine + 1, col = completionContext.TriggerLineOffset;

            ITextBuffer buf = this.Buffer;

            // completionChar may be a space even if the current char isn't, when ctrl-space is fired t
            int  currentPosition = buf.CursorPosition - 1;
            char currentChar     = buf.GetCharAt(currentPosition);
            char previousChar    = buf.GetCharAt(currentPosition - 1);

            //decide whether completion will be auto-activated, to avoid unnecessary
            //parsing, which hurts editor responsiveness
            if (!forced)
            {
                //
                if (tracker.Engine.CurrentState is S.XmlFreeState && !(currentChar == '<' || currentChar == '>'))
                {
                    return(null);
                }

                if (tracker.Engine.CurrentState is S.XmlNameState &&
                    tracker.Engine.CurrentState.Parent is S.XmlAttributeState && previousChar != ' ')
                {
                    return(null);
                }

                if (tracker.Engine.CurrentState is S.XmlAttributeValueState &&
                    !(previousChar == '\'' || previousChar == '"' || currentChar == '\'' || currentChar == '"'))
                {
                    return(null);
                }
            }

            //tag completion
            if (currentChar == '<')
            {
                CodeCompletionDataProvider cp = new CodeCompletionDataProvider(null, GetAmbience());

                if (tracker.Engine.CurrentState is S.XmlFreeState)
                {
                    S.XElement el = tracker.Engine.Nodes.Peek() as S.XElement;
                    AddTagCompletionData(cp, el);
                }
                return(cp);
            }

            //closing tag completion
            if (tracker.Engine.CurrentState is S.XmlFreeState && currentPosition - 1 > 0 && currentChar == '>')
            {
                //get name of current node in document that's being ended
                S.XElement el = tracker.Engine.Nodes.Peek() as S.XElement;
                if (el != null && el.Position.End >= currentPosition && !el.IsClosed && el.IsNamed)
                {
                    CodeCompletionDataProvider cp = new CodeCompletionDataProvider(null, GetAmbience());
                    cp.AddCompletionData(
                        new MonoDevelop.XmlEditor.Completion.XmlTagCompletionData(
                            String.Concat("</", el.Name.FullName, ">"), 0, true)
                        );
                    return(cp);
                }
            }

            //attributes names within tags
            if (tracker.Engine.CurrentState is S.XmlTagState && forced ||
                (tracker.Engine.CurrentState is S.XmlNameState &&
                 tracker.Engine.CurrentState.Parent is S.XmlAttributeState &&
                 tracker.Engine.CurrentStateLength == 1)
                )
            {
                int        peekp = (tracker.Engine.CurrentState is S.XmlTagState) ? 0 : 1;
                S.XElement el    = (S.XElement)tracker.Engine.Nodes.Peek(peekp);

                // HACK
                S.XElement pel = tracker.Engine.Nodes.Peek(peekp + 1) as S.XElement;
                if (el.Parent == null && pel != null)
                {
                    pel.AddChildNode(el);
                }

                //attributes
                if (el != null && el.Name.IsValid && (forced || char.IsWhiteSpace(currentChar) ||
                                                      (char.IsWhiteSpace(previousChar) && char.IsLetter(currentChar))))
                {
                    CodeCompletionDataProvider cp = new CodeCompletionDataProvider(null, GetAmbience());
                    if (!forced)
                    {
                        triggerWordLength = 1;
                    }

                    AddAttributeCompletionData(cp, el);
                    return(cp);
                }
            }

            //attribute values
            //determine whether to trigger completion within attribute values quotes
            if ((tracker.Engine.CurrentState is S.XmlDoubleQuotedAttributeValueState ||
                 tracker.Engine.CurrentState is S.XmlSingleQuotedAttributeValueState)
                //trigger on the opening quote
                && (tracker.Engine.CurrentStateLength == 0
                    //or trigger on first letter of value, if unforced
                    || (!forced && tracker.Engine.CurrentStateLength == 1))
                )
            {
                S.XAttribute att = (S.XAttribute)tracker.Engine.Nodes.Peek();

                if (att.IsNamed)
                {
                    S.XElement el = (S.XElement)tracker.Engine.Nodes.Peek(1);

                    // HACK
                    S.XElement pel = tracker.Engine.Nodes.Peek(2) as S.XElement;
                    if (el.Parent == null && pel != null)
                    {
                        pel.AddChildNode(el);
                    }

                    char next = ' ';
                    if (currentPosition + 1 < buf.Length)
                    {
                        next = buf.GetCharAt(currentPosition + 1);
                    }

                    char compareChar = (tracker.Engine.CurrentStateLength == 0)? currentChar : previousChar;
                    Console.WriteLine("ppa: " + att.Value);

                    if ((compareChar == '"' || compareChar == '\'') &&
                        (next == compareChar || char.IsWhiteSpace(next))
                        )
                    {
                        //if triggered by first letter of value, grab that letter
                        if (tracker.Engine.CurrentStateLength == 1)
                        {
                            triggerWordLength = 1;
                        }

                        CodeCompletionDataProvider cp = new CodeCompletionDataProvider(null, GetAmbience());
                        AddAttributeValueCompletionData(cp, el, att);
                        return(cp);
                    }
                }
            }

            return(null);
        }
Esempio n. 4
0
        public override State PushChar(char c, IParseContext context, ref string rollback)
        {
            XAttribute att = context.Nodes.Peek() as XAttribute;

            if (c == '<')
            {
                //parent handles message
                if (att != null)
                {
                    context.Nodes.Pop();
                }
                rollback = string.Empty;
                return(Parent);
            }

            //state has just been entered
            if (context.CurrentStateLength == 1)
            {
                if (context.PreviousState is XmlNameState)
                {
                    Debug.Assert(att.IsNamed);
                    context.StateTag = GETTINGEQ;
                }
                else if (context.PreviousState is XmlAttributeValueState)
                {
                    //Got value, so end attribute
                    context.Nodes.Pop();
                    att.End(context.LocationMinus(1));
                    IAttributedXObject element = (IAttributedXObject)context.Nodes.Peek();
                    element.Attributes.AddAttribute(att);
                    rollback = string.Empty;
                    return(Parent);
                }
                else
                {
                    //starting a new attribute
                    Debug.Assert(att == null);
                    Debug.Assert(context.StateTag == NAMING);
                    att = new XAttribute(context.LocationMinus(1));
                    context.Nodes.Push(att);
                    rollback = string.Empty;
                    return(XmlNameState);
                }
            }

            if (c == '>')
            {
                context.LogWarning("Attribute ended unexpectedly with '>' character.");
                if (att != null)
                {
                    context.Nodes.Pop();
                }
                rollback = string.Empty;
                return(Parent);
            }

            if (context.StateTag == GETTINGEQ)
            {
                if (char.IsWhiteSpace(c))
                {
                    return(null);
                }
                else if (c == '=')
                {
                    context.StateTag = GETTINGVAL;
                    return(null);
                }
            }
            else if (context.StateTag == GETTINGVAL)
            {
                if (char.IsWhiteSpace(c))
                {
                    return(null);
                }
                else if (c == '"')
                {
                    return(DoubleQuotedAttributeValueState);
                }
                else if (c == '\'')
                {
                    return(SingleQuotedAttributeValueState);
                }
                else if (char.IsLetterOrDigit(c))
                {
                    rollback = string.Empty;
                    return(UnquotedAttributeValueState);
                }
            }

            if (Char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsWhiteSpace(c))
            {
                string err;
                if (context.StateTag == GETTINGEQ)
                {
                    context.LogError("Expecting = in attribute, got " + c + ".");
                }
                else if (context.StateTag == GETTINGVAL)
                {
                    context.LogError("Expecting attribute value, got " + c + ".");
                }
                else
                {
                    context.LogError("Unexpected character '" + c + "' in attribute.");
                }

                if (att != null)
                {
                    context.Nodes.Pop();
                }
                rollback = string.Empty;
                return(Parent);
            }

            rollback = string.Empty;
            return(Parent);
        }