diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs index 12f32eeb1a..c4b8184ee1 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataHelper.cs @@ -44,70 +44,95 @@ namespace ICSharpCode.XamlBinding public static XamlContext ResolveContext(string text, string fileName, int line, int col) { + DebugTimer.Start(); + int offset = Utils.GetOffsetFromFilePos(text, line, col); if (offset == -1) throw new InvalidOperationException("No valid file position: " + line + " " + col); ParseInformation info = ParserService.GetParseInformation(fileName); - XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(text, offset); string attribute = XmlParser.GetAttributeNameAtIndex(text, offset); bool inAttributeValue = XmlParser.IsInsideAttributeValue(text, offset); - string attributeValue = ""; - if (inAttributeValue) - attributeValue = XmlParser.GetAttributeValueAtIndex(text, offset); + string attributeValue = XmlParser.GetAttributeValueAtIndex(text, offset); int offsetFromValueStart = Utils.GetOffsetFromValueStart(text, offset); int elementStartIndex = XmlParser.GetActiveElementStartIndex(text, offset); AttributeValue value = MarkupExtensionParser.ParseValue(attributeValue); XamlContextDescription description = XamlContextDescription.None; - if (path == null || path.Elements.Count == 0) { - path = XmlParser.GetParentElementPath(text.Substring(0, offset)); - } else { - description = XamlContextDescription.AtTag; + Dictionary xmlnsDefs = new Dictionary(); + + // TODO : does not work when trying to resolve , if xmlns declarartion is in + using (XmlTextReader reader = Utils.CreateReaderAtTarget(text, line, col)) { + xmlnsDefs.AddRange(reader.GetNamespacesInScope(XmlNamespaceScope.All)); } + + QualifiedName active = ResolveCurrentElement(text, elementStartIndex, xmlnsDefs); if (text[offset] == '>') description = XamlContextDescription.None; string wordBeforeIndex = text.GetWordBeforeOffset(offset); + if (active != null) + description = XamlContextDescription.AtTag; + if (elementStartIndex > -1 && (char.IsWhiteSpace(text[offset]) || !string.IsNullOrEmpty(attribute) || Extensions.Is(text[offset], '"', '\'') || !wordBeforeIndex.StartsWith("<"))) description = XamlContextDescription.InTag; - if (inAttributeValue) { - description = XamlContextDescription.InAttributeValue; + if (inAttributeValue) { + description = XamlContextDescription.InAttributeValue; - if (value != null && !value.IsString) - description = XamlContextDescription.InMarkupExtension; + if (value != null && !value.IsString) + description = XamlContextDescription.InMarkupExtension; - if (attributeValue.StartsWith("{}", StringComparison.Ordinal) && attributeValue.Length > 2) - description = XamlContextDescription.InAttributeValue; - } + if (attributeValue.StartsWith("{}", StringComparison.Ordinal) && attributeValue.Length > 2) + description = XamlContextDescription.InAttributeValue; + } if (Utils.IsInsideXmlComment(text, offset)) description = XamlContextDescription.InComment; - Dictionary xmlnsDefs = new Dictionary(); - - // TODO : does not work when trying to resolve , if xmlns declarartion is in - using (XmlTextReader reader = Utils.CreateReaderAtTarget(text, line, col)) { - xmlnsDefs.AddRange(reader.GetNamespacesInScope(XmlNamespaceScope.All)); - } + var context = new XamlContext() { Description = description, + ActiveElement = active, AttributeName = attribute, AttributeValue = value, RawAttributeValue = attributeValue, ValueStartOffset = offsetFromValueStart, - Path = (path == null || path.Elements.Count == 0) ? null : path, XmlnsDefinitions = xmlnsDefs, ParseInformation = info }; + DebugTimer.Stop("ResolveContext"); + return context; } + static QualifiedName ResolveCurrentElement(string text, int offset, Dictionary xmlnsDefinitions) + { + if (offset < 0) + return null; + + string elementName = text.GetWordAfterOffset(offset + 1); + + string prefix = ""; + string element = ""; + + if (elementName.IndexOf(':') > -1) { + string[] data = elementName.Split(':'); + prefix = data[0]; + element = data[1]; + } else { + element = elementName; + } + + string xmlns = xmlnsDefinitions.ContainsKey(prefix) ? xmlnsDefinitions[prefix] : string.Empty; + + return new QualifiedName(element, xmlns, prefix); + } + public static XamlCompletionContext ResolveCompletionContext(ITextEditor editor, char typedValue) { var context = new XamlCompletionContext(ResolveContext(editor.Document.Text, editor.FileName, editor.Caret.Line, editor.Caret.Column)) { @@ -120,7 +145,7 @@ namespace ICSharpCode.XamlBinding static List CreateListForAttributeName(XamlCompletionContext context, string[] existingItems) { - QualifiedName lastElement = context.Path.Elements.LastOrDefault(); + QualifiedName lastElement = context.ActiveElement; XamlCompilationUnit cu = context.ParseInformation.BestCompilationUnit as XamlCompilationUnit; if (cu == null) return null; @@ -163,7 +188,7 @@ namespace ICSharpCode.XamlBinding foreach (string @namespace in content.NamespaceNames) { if (!string.IsNullOrEmpty(@namespace)) - list.Add(new XmlnsCompletionItem(@namespace, content.AssemblyName)); + list.Add(new XmlnsCompletionItem(@namespace, content.AssemblyName)); } } @@ -271,7 +296,7 @@ namespace ICSharpCode.XamlBinding var existingAttribs = Utils.GetListOfExistingAttributeNames(editor.Document.Text, editor.Caret.Line, editor.Caret.Column); list.Items.AddRange(CreateListForAttributeName(context, existingAttribs)); - QualifiedName last = context.Path.Elements[context.Path.Elements.Count - 1]; + QualifiedName last = context.ActiveElement; TypeResolveResult trr = new XamlResolver().Resolve(new ExpressionResult(last.Name, context), info, editor.Document.Text) as TypeResolveResult; @@ -429,30 +454,28 @@ namespace ICSharpCode.XamlBinding break; case ClassType.Delegate: IMethod invoker = c.Methods.Where(method => method.Name == "Invoke").FirstOrDefault(); - if (invoker != null) { - if (context.Path != null) { - var item = context.Path.Elements.LastOrDefault(); - var evt = ResolveAttribute(context.AttributeName, context) as IEvent; - if (evt == null) - break; - - int offset = XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset); - - if (offset == -1) - break; - - var loc = context.Editor.Document.OffsetToPosition(offset); - - string prefix = Utils.GetXamlNamespacePrefix(context); - string name = Utils.GetAttributeValue(context.Editor.Document.Text, loc.Line, loc.Column + 1, "name"); - if (string.IsNullOrEmpty(name)) - name = Utils.GetAttributeValue(context.Editor.Document.Text, loc.Line, loc.Column + 1, (string.IsNullOrEmpty(prefix) ? "" : prefix + ":") + "name"); - - yield return new NewEventCompletionItem(evt, (string.IsNullOrEmpty(name)) ? item.Name : name); - - foreach (var eventItem in CompletionDataHelper.AddMatchingEventHandlers(context.Editor, invoker)) - yield return eventItem; - } + if (invoker != null && context.ActiveElement != null) { + var item = context.ActiveElement; + var evt = ResolveAttribute(context.AttributeName, context) as IEvent; + if (evt == null) + break; + + int offset = XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset); + + if (offset == -1) + break; + + var loc = context.Editor.Document.OffsetToPosition(offset); + + string prefix = Utils.GetXamlNamespacePrefix(context); + string name = Utils.GetAttributeValue(context.Editor.Document.Text, loc.Line, loc.Column + 1, "name"); + if (string.IsNullOrEmpty(name)) + name = Utils.GetAttributeValue(context.Editor.Document.Text, loc.Line, loc.Column + 1, (string.IsNullOrEmpty(prefix) ? "" : prefix + ":") + "name"); + + yield return new NewEventCompletionItem(evt, (string.IsNullOrEmpty(name)) ? item.Name : name); + + foreach (var eventItem in CompletionDataHelper.AddMatchingEventHandlers(context.Editor, invoker)) + yield return eventItem; } break; } @@ -711,9 +734,9 @@ namespace ICSharpCode.XamlBinding result.AddRange(attachedEvents .Select( item => new XamlCodeCompletionItem( - new DefaultEvent(c, GetEventNameFromField(item)) { - ReturnType = GetAttachedEventDelegateType(item, c) - }, + new DefaultEvent(c, GetEventNameFromField(item)) { + ReturnType = GetAttachedEventDelegateType(item, c) + }, (string.IsNullOrEmpty(ns.Key) ? "" : ns.Key + ":") + c.Name + "." + item.Name.Remove(item.Name.Length - "Event".Length) ) ) diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs index 4b4646cfba..ddaec27bdf 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.XamlBinding } break; case '.': - if (context.Path != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { + if (context.ActiveElement != null && !XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset)) { context.Description = XamlContextDescription.AtTag; list = CompletionDataHelper.CreateListForContext(editor, context); editor.ShowCompletionWindow(list); @@ -85,7 +85,7 @@ namespace ICSharpCode.XamlBinding } break; case ':': - if (context.Path != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) { + if (context.ActiveElement != null && XmlParser.GetQualifiedAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset) == null) { if (!context.AttributeName.StartsWith("xmlns")) { list = CompletionDataHelper.CreateListForContext(editor, context); editor.ShowCompletionWindow(list); @@ -136,7 +136,7 @@ namespace ICSharpCode.XamlBinding XamlCompletionContext context = CompletionDataHelper.ResolveCompletionContext(editor, ' '); context.Forced = true; Core.LoggingService.Debug(context); - if (context.Path != null) { + if (context.ActiveElement != null) { if (!XmlParser.IsInsideAttributeValue(editor.Document.Text, editor.Caret.Offset) && context.Description != XamlContextDescription.InAttributeValue) { var list = CompletionDataHelper.CreateListForContext(editor, context) as XamlCompletionItemList; string starter = editor.GetWordBeforeCaret().Trim('<', '>'); @@ -160,7 +160,7 @@ namespace ICSharpCode.XamlBinding editor.ShowInsightWindow(CompletionDataHelper.MemberInsight(mrr)); } - if (context.Path.Elements.LastOrDefault().Name == "Setter") + if (context.ActiveElement.Name == "Setter") DoSetterCompletion(context, completionList); completionList.SortItems(); diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs index 3eee87e513..b30fabf14e 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs @@ -19,7 +19,7 @@ using ICSharpCode.XmlEditor; namespace ICSharpCode.XamlBinding { public class XamlContext : ExpressionContext { - public XmlElementPath Path { get; set; } + public QualifiedName ActiveElement { get; set; } public string AttributeName { get; set; } public AttributeValue AttributeValue { get; set; } public string RawAttributeValue { get; set; } @@ -34,16 +34,6 @@ namespace ICSharpCode.XamlBinding { return true; } - - public override string ToString() - { - return "[XamlContext" + - " Description: " + Description + - " Path: " + Path + - " AttributeName: " + AttributeName + - " ValueStartOffset: " + ValueStartOffset + - " ]"; - } } public class XamlCompletionContext : XamlContext { @@ -51,11 +41,11 @@ namespace ICSharpCode.XamlBinding public XamlCompletionContext(XamlContext context) { + this.ActiveElement = context.ActiveElement; this.AttributeName = context.AttributeName; this.AttributeValue = context.AttributeValue; this.Description = context.Description; this.ParseInformation = context.ParseInformation; - this.Path = context.Path; this.RawAttributeValue = context.RawAttributeValue; this.ValueStartOffset = context.ValueStartOffset; this.XmlnsDefinitions = context.XmlnsDefinitions; diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs index 9428c59940..0e1cb4e40f 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlResolver.cs @@ -45,7 +45,8 @@ namespace ICSharpCode.XamlBinding case XamlContextDescription.InAttributeValue: MemberResolveResult mrr = ResolveAttribute(context.AttributeName); if (mrr != null) { - return ResolveAttributeValue(mrr.ResolvedMember, resolveExpression) ?? mrr; + var rr = ResolveAttributeValue(mrr.ResolvedMember, resolveExpression) ?? mrr; + return rr; } break; case XamlContextDescription.InMarkupExtension: @@ -206,7 +207,7 @@ namespace ICSharpCode.XamlBinding MemberResolveResult ResolveAttribute(string attributeName) { - if (context.Path == null) { + if (context.ActiveElement == null) { return null; } string attributeXmlNamespace; @@ -226,7 +227,7 @@ namespace ICSharpCode.XamlBinding return ResolveProperty(attributeXmlNamespace, className, attributeName, true); } else { - ICSharpCode.XmlEditor.QualifiedName lastElement = context.Path.Elements.LastOrDefault(); + QualifiedName lastElement = context.ActiveElement; return ResolveProperty(lastElement.Namespace, lastElement.Name, attributeName, false); } }