Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit 1663591

Browse files
fix #396 - x:Shared missing in XAML CC
1 parent c8a714b commit 1663591

7 files changed

Lines changed: 143 additions & 45 deletions

File tree

src/AddIns/BackendBindings/XamlBinding/XamlBinding/CompletionDataGenerator.cs

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,26 @@ public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, b
122122
{
123123
if (context.ParseInformation == null)
124124
return EmptyList<ICompletionItem>.Instance;
125+
125126
List<ICompletionItem> result = new List<ICompletionItem>();
126127
AXmlElement last = context.ParentElement;
127128
ITextEditor editor = context.Editor;
128129
compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
129130
IUnresolvedFile file = context.ParseInformation.UnresolvedFile;
130-
var items = GetClassesFromContext(context);
131+
132+
foreach (string item in XamlConst.GetAllowedItems(context)) {
133+
result.Add(new XamlCompletionItem(item));
134+
}
135+
131136
IType rt = null;
132137

133138
if (last != null) {
139+
if (string.Equals(last.Prefix, context.XamlNamespacePrefix, StringComparison.OrdinalIgnoreCase)) {
140+
if (string.Equals(last.LocalName, "Members", StringComparison.OrdinalIgnoreCase))
141+
return result;
142+
if (string.Equals(last.LocalName, "Code", StringComparison.OrdinalIgnoreCase))
143+
return result;
144+
}
134145
// If we have an element that is not a property or an incomplete
135146
// definition => interpret element as a type.
136147
XamlResolver resolver = new XamlResolver(compilation);
@@ -172,6 +183,8 @@ public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, b
172183
.ToList();
173184
}
174185

186+
var items = GetClassesFromContext(context);
187+
175188
foreach (var ns in items) {
176189
foreach (ITypeDefinition td in ns.Value) {
177190
if (td.Kind != TypeKind.Class && (!includeAbstract || td.Kind != TypeKind.Interface))
@@ -198,15 +211,6 @@ public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, b
198211
// result.Add(new XamlCodeCompletionItem(itemClass, last.Prefix));
199212
// }
200213

201-
var xamlItems = XamlConst.XamlNamespaceAttributes.AsEnumerable();
202-
203-
if (XamlConst.EnableXaml2009)
204-
xamlItems = XamlConst.XamlBuiltInTypes.Concat(xamlItems);
205-
206-
foreach (string item in xamlItems) {
207-
result.Add(new XamlCompletionItem(context.XamlNamespacePrefix + ":" + item));
208-
}
209-
210214
return result;
211215
}
212216

@@ -266,8 +270,10 @@ IList<ICompletionItem> CreateAttributeList(XamlCompletionContext context, bool i
266270
string xamlPrefix = context.XamlNamespacePrefix;
267271
string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":";
268272

269-
if (lastElement.Prefix == context.XamlNamespacePrefix && XamlConst.IsBuiltin(lastElement.LocalName))
270-
return EmptyList<ICompletionItem>.Instance;
273+
list.AddRange(XamlConst.GetAllowedItems(context).Select(item => new XamlCompletionItem(item)));
274+
275+
if (string.Equals(lastElement.Prefix, context.XamlNamespacePrefix, StringComparison.OrdinalIgnoreCase) && XamlConst.IsBuiltin(lastElement.LocalName))
276+
return list;
271277

272278
if (lastElement.LocalName.EndsWith(".", StringComparison.OrdinalIgnoreCase) || context.PressedKey == '.') {
273279
if (type.Kind == TypeKind.Unknown)
@@ -279,16 +285,9 @@ IList<ICompletionItem> CreateAttributeList(XamlCompletionContext context, bool i
279285
}
280286
AddAttachedProperties(type.GetDefinition(), list);
281287
} else {
282-
if (type.Kind == TypeKind.Unknown) {
283-
list.Add(new XamlCompletionItem(xKey + "Uid"));
284-
} else {
288+
if (type.Kind != TypeKind.Unknown) {
285289
AddAttributes(type, list, includeEvents);
286290
list.AddRange(GetListOfAttached(context, null, includeEvents, true));
287-
list.AddRange(
288-
XamlConst.XamlNamespaceAttributes
289-
.Where(localName => XamlConst.IsAttributeAllowed(context.InRoot, localName))
290-
.Select(item => new XamlCompletionItem(xKey + item))
291-
);
292291
}
293292
}
294293

@@ -384,11 +383,11 @@ public IEnumerable<ICompletionItem> MemberCompletion(XamlCompletionContext conte
384383
ITextEditor editor = context.Editor;
385384
compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
386385

386+
string xamlPrefix = context.XamlNamespacePrefix;
387+
string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":";
388+
387389
if (type.Name == typeof(System.Nullable<>).Name) {
388-
string nullExtensionName = "Null";
389-
if (!string.IsNullOrEmpty(context.XamlNamespacePrefix))
390-
nullExtensionName = context.XamlNamespacePrefix + ":" + nullExtensionName;
391-
yield return new XamlCompletionItem("{" + nullExtensionName + "}");
390+
yield return new XamlCompletionItem("{" + xKey + "Null}");
392391
type = type.TypeArguments.FirstOrDefault();
393392
if (type == null) yield break;
394393
}
@@ -397,6 +396,18 @@ public IEnumerable<ICompletionItem> MemberCompletion(XamlCompletionContext conte
397396

398397
if (definition == null) yield break;
399398

399+
definition.IsCollectionType();
400+
401+
switch (definition.KnownTypeCode) {
402+
case KnownTypeCode.Array:
403+
case KnownTypeCode.ICollection:
404+
case KnownTypeCode.ICollectionOfT:
405+
case KnownTypeCode.IEnumerable:
406+
case KnownTypeCode.IEnumerableOfT:
407+
yield return new XamlCompletionItem("{" + xKey + "Array}");
408+
break;
409+
}
410+
400411
switch (definition.Kind) {
401412
case TypeKind.Class:
402413
IType typeName;

src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,17 @@ public static bool IsListType(this IType thisValue)
398398
return thisValue.GetAllBaseTypeDefinitions().Any(t => t.FullName == "System.Collections.IList");
399399
}
400400

401+
public static bool Implements(this IType thisValue, IType interfaceType)
402+
{
403+
if (thisValue == null)
404+
throw new ArgumentNullException("thisValue");
405+
if (interfaceType == null)
406+
throw new ArgumentNullException("interfaceType");
407+
if (interfaceType.Kind != TypeKind.Interface)
408+
throw new ArgumentException("must be TypeKind.Interface", "interfaceType");
409+
return thisValue.GetAllBaseTypes().Any(t => t.Equals(interfaceType));
410+
}
411+
401412
public static bool HasAttached(this ITypeDefinition thisValue, bool lookForProperties, bool lookForEvents)
402413
{
403414
if (!lookForProperties && !lookForEvents)

src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCompletionItemList.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public override void Complete(CompletionContext context, ICompletionItem item)
8383
XamlCompletionItem cItem = item as XamlCompletionItem;
8484

8585
if (xamlContext.Description == XamlContextDescription.InTag) {
86-
if (cItem.Entity.SymbolKind == SymbolKind.Property || cItem.Entity.SymbolKind == SymbolKind.Event) {
86+
if (cItem.Entity == null || cItem.Entity.SymbolKind == SymbolKind.Property || cItem.Entity.SymbolKind == SymbolKind.Event) {
8787
context.Editor.Document.Insert(context.EndOffset, "=\"\"");
8888
context.CompletionCharHandled = context.CompletionChar == '=';
8989
context.Editor.Caret.Offset--;

src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlConst.cs

Lines changed: 85 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
using System.Collections.Generic;
2121
using System.Collections.ObjectModel;
2222
using System.Linq;
23+
using System.Windows;
24+
using System.Xml.Serialization;
25+
using ICSharpCode.NRefactory.TypeSystem;
26+
using ICSharpCode.NRefactory.Semantics;
27+
using ICSharpCode.SharpDevelop;
2328

2429
namespace ICSharpCode.XamlBinding
2530
{
@@ -28,33 +33,22 @@ namespace ICSharpCode.XamlBinding
2833
/// </summary>
2934
public static class XamlConst
3035
{
31-
public const bool EnableXaml2009 = true;
32-
3336
// [XAML 2009]
3437
public static readonly List<string> XamlBuiltInTypes = new List<string> {
3538
"Object", "Boolean", "Char", "String", "Decimal", "Single", "Double",
3639
"Int16", "Int32", "Int64", "TimeSpan", "Uri", "Byte", "Array", "List", "Dictionary",
37-
// This is no built in type, but a markup extension
3840
"Reference"
3941
};
4042

4143
public static readonly ReadOnlyCollection<string> XamlNamespaceAttributes = new List<string> {
42-
"Class", "ClassModifier", "FieldModifier", "Name", "Subclass", "TypeArguments", "Uid", "Key"
43-
}.AsReadOnly();
44-
45-
public static readonly ReadOnlyCollection<string> RootOnlyElements = new List<string> {
46-
"Class", "ClassModifier", "Subclass"
47-
}.AsReadOnly();
48-
49-
public static readonly ReadOnlyCollection<string> ChildOnlyElements = new List<string> {
50-
"FieldModifier"
44+
"Class", "ClassModifier", "FieldModifier", "Name", "Subclass", "TypeArguments", "Uid", "Key", "Shared"
5145
}.AsReadOnly();
5246

5347
/// <summary>
5448
/// values: http://schemas.microsoft.com/winfx/2006/xaml/presentation,
5549
/// http://schemas.microsoft.com/netfx/2007/xaml/presentation
5650
/// </summary>
57-
public static readonly string[] WpfXamlNamespaces = new[] {
51+
public static readonly string[] WpfXamlNamespaces = {
5852
"http://schemas.microsoft.com/winfx/2006/xaml/presentation",
5953
"http://schemas.microsoft.com/netfx/2007/xaml/presentation"
6054
};
@@ -88,11 +82,86 @@ public static bool IsBuiltin(string localName)
8882
}
8983

9084
/// <summary>
91-
/// Returns true if the given attribute is allowed in the current element.
85+
/// Returns the list of allow XAML2009 completion items.
9286
/// </summary>
93-
public static bool IsAttributeAllowed(bool inRoot, string localName)
87+
public static IEnumerable<string> GetAllowedItems(XamlCompletionContext context)
9488
{
95-
return inRoot ? !ChildOnlyElements.Contains(localName) : !RootOnlyElements.Contains(localName);
89+
string xamlPrefix = context.XamlNamespacePrefix;
90+
string xKey = string.IsNullOrEmpty(xamlPrefix) ? "" : xamlPrefix + ":";
91+
var compilation = SD.ParserService.GetCompilationForFile(context.Editor.FileName);
92+
var resolver = new XamlAstResolver(compilation, context.ParseInformation);
93+
// TODO : add support for x:Key as attribute element (XAML 2009 only)
94+
95+
switch (context.Description) {
96+
case XamlContextDescription.AtTag:
97+
if (context.ParentElement != null && string.Equals(context.ParentElement.Name, xKey + "Members", StringComparison.OrdinalIgnoreCase)) {
98+
yield return xKey + "Member";
99+
yield return xKey + "Property";
100+
} else if (context.ParentElement == context.RootElement && context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase))) {
101+
yield return xKey + "Code";
102+
yield return xKey + "Members";
103+
} else {
104+
if (context.ParentElement != null && string.Equals(context.ParentElement.Name, xKey + "Code", StringComparison.OrdinalIgnoreCase))
105+
yield break;
106+
yield return xKey + "Array";
107+
yield return xKey + "Boolean";
108+
yield return xKey + "Byte";
109+
yield return xKey + "Char";
110+
yield return xKey + "Decimal";
111+
yield return xKey + "Dictionary";
112+
yield return xKey + "Double";
113+
yield return xKey + "Int16";
114+
yield return xKey + "Int32";
115+
yield return xKey + "Int64";
116+
yield return xKey + "List";
117+
yield return xKey + "Object";
118+
yield return xKey + "Reference";
119+
yield return xKey + "Single";
120+
yield return xKey + "String";
121+
yield return xKey + "TimeSpan";
122+
yield return xKey + "Uri";
123+
if (context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase)))
124+
yield return xKey + "Members";
125+
}
126+
break;
127+
case XamlContextDescription.InTag:
128+
yield return xKey + "Uid";
129+
if (context.InRoot) {
130+
yield return xKey + "Class";
131+
yield return xKey + "ClassModifier";
132+
yield return xKey + "Subclass";
133+
yield return xKey + "Name";
134+
} else {
135+
var resourceDictionaryType = compilation.FindType(typeof(ResourceDictionary));
136+
if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Array", StringComparison.OrdinalIgnoreCase)) {
137+
yield return "Type";
138+
} else if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Member", StringComparison.OrdinalIgnoreCase)) {
139+
yield return "Name";
140+
} else if (context.ActiveElement != null && string.Equals(context.ActiveElement.Name, xKey + "Property", StringComparison.OrdinalIgnoreCase)) {
141+
yield return "Name";
142+
yield return "Type";
143+
} else if (context.RootElement.Attributes.Any(attr => string.Equals(attr.Name, xKey + "Class", StringComparison.OrdinalIgnoreCase))) {
144+
yield return xKey + "FieldModifier";
145+
yield return xKey + "Name";
146+
} else {
147+
yield return xKey + "Name";
148+
}
149+
150+
if (context.ParentElement != null) {
151+
var rr = resolver.ResolveElement(context.ParentElement);
152+
if (rr != null) {
153+
if (rr.Type.Equals(resourceDictionaryType)) {
154+
yield return xKey + "Key";
155+
yield return xKey + "Shared";
156+
} else if (rr.Type.TypeParameterCount > 0) {
157+
yield return xKey + "TypeArguments";
158+
}
159+
}
160+
}
161+
}
162+
break;
163+
}
164+
yield break;
96165
}
97166
}
98167
}

src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContext.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public class XamlContext
9494
{
9595
public AXmlElement ActiveElement { get; set; }
9696
public AXmlElement ParentElement { get; set; }
97+
public AXmlElement RootElement { get; set; }
9798
public ReadOnlyCollection<AXmlElement> Ancestors { get; set; }
9899
public AXmlAttribute Attribute { get; set; }
99100
public AttributeValue AttributeValue { get; set; }
@@ -131,6 +132,7 @@ public XamlCompletionContext(XamlContext context)
131132
this.AttributeValue = context.AttributeValue;
132133
this.Description = context.Description;
133134
this.ParentElement = context.ParentElement;
135+
this.RootElement = context.RootElement;
134136
this.ParseInformation = context.ParseInformation;
135137
this.RawAttributeValue = context.RawAttributeValue;
136138
this.ValueStartOffset = context.ValueStartOffset;

src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlContextResolver.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public static XamlContext ResolveContext(FileName fileName, ITextSource fileCont
5959
string xamlNamespacePrefix = string.Empty;
6060

6161
var item = currentData;
62+
AXmlElement root = null;
6263

6364
while (item != document) {
6465
if (item is AXmlElement) {
@@ -78,8 +79,11 @@ public static XamlContext ResolveContext(FileName fileName, ITextSource fileCont
7879
xamlNamespacePrefix = attr.LocalName;
7980
}
8081

81-
if (!wasAXmlElement && item.Parent is AXmlDocument)
82-
isRoot = true;
82+
if (element.Parent is AXmlDocument) {
83+
root = element;
84+
if (!wasAXmlElement)
85+
isRoot = true;
86+
}
8387

8488
wasAXmlElement = true;
8589
}
@@ -91,7 +95,7 @@ public static XamlContext ResolveContext(FileName fileName, ITextSource fileCont
9195

9296
AXmlElement active = null;
9397
AXmlElement parent = null;
94-
98+
9599
if (currentData is AXmlAttribute) {
96100
AXmlAttribute a = currentData as AXmlAttribute;
97101
int valueStartOffset = a.ValueSegment.Offset + 1;
@@ -140,6 +144,7 @@ public static XamlContext ResolveContext(FileName fileName, ITextSource fileCont
140144
Description = description,
141145
ActiveElement = active,
142146
ParentElement = parent,
147+
RootElement = root,
143148
Ancestors = ancestors.AsReadOnly(),
144149
Attribute = xAttribute,
145150
InRoot = isRoot,

src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignPanelHitTestResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
namespace ICSharpCode.WpfDesign
2525
{
2626
/// <summary>
27-
/// Describes the result of a <see cref="IDesignPanel.HitTest(Point, bool, bool)"/> call.
27+
/// Describes the result of a <see cref="IDesignPanel.HitTest(Point, bool, bool, HitTestType)"/> call.
2828
/// </summary>
2929
public struct DesignPanelHitTestResult : IEquatable<DesignPanelHitTestResult>
3030
{

0 commit comments

Comments
 (0)