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

Commit 9d237df

Browse files
fix #547: XAML CC does not support fully qualified property names in <Setter>
1 parent b6d3fd1 commit 9d237df

4 files changed

Lines changed: 82 additions & 16 deletions

File tree

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,38 @@ public IList<ICompletionItem> CreateElementList(XamlCompletionContext context, b
214214
return result;
215215
}
216216

217+
public IEnumerable<ICompletionItem> GetTypesForPropEventNameCompletion(XamlCompletionContext context, bool includeAbstract)
218+
{
219+
ITextEditor editor = context.Editor;
220+
compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
221+
IUnresolvedFile file = context.ParseInformation.UnresolvedFile;
222+
223+
var utd = file.GetInnermostTypeDefinition(editor.Caret.Location);
224+
ITypeDefinition currentTypeDef = null;
225+
if (utd != null) {
226+
currentTypeDef = utd.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition();
227+
}
228+
229+
MemberLookup memberLookup = new MemberLookup(currentTypeDef, compilation.MainAssembly);
230+
231+
var items = GetClassesFromContext(context);
232+
233+
foreach (var ns in items) {
234+
foreach (ITypeDefinition td in ns.Value) {
235+
if (td.Kind != TypeKind.Class && (!includeAbstract || td.Kind != TypeKind.Interface))
236+
continue;
237+
if (td.IsStatic || (!includeAbstract && td.IsAbstract) || td.IsDerivedFrom(KnownTypeCode.Attribute))
238+
continue;
239+
if (td.Kind == TypeKind.Class && !td.GetConstructors().Any(m => memberLookup.IsAccessible(m, false)))
240+
continue;
241+
string fullName = td.Name;
242+
if (!string.IsNullOrEmpty(ns.Key))
243+
fullName = ns.Key + ":" + fullName;
244+
yield return new XamlCompletionItem(fullName, td);
245+
}
246+
}
247+
}
248+
217249
void AddClosingTagCompletion(XamlContext context, DefaultCompletionItemList list, XamlAstResolver resolver)
218250
{
219251
if (context.ParentElement != null && !context.InRoot) {

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,6 @@ public static bool Is(char value, params char[] choice)
166166
return false;
167167
}
168168

169-
public static IEnumerable<T> Add<T>(this IEnumerable<T> items, params T[] addItems)
170-
{
171-
return items.Concat(addItems);
172-
}
173-
174169
public static string GetWordBeforeCaretExtended(this ITextEditor editor)
175170
{
176171
IDocumentLine line = editor.Document.GetLine(editor.Caret.Line);

src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ public static MarkupExtensionInfo GetMarkupExtensionAtPosition(MarkupExtensionIn
144144
return tmp;
145145
}
146146

147-
public static string LookForTargetTypeValue(XamlContext context, out bool isExplicit, params string[] elementName) {
147+
public static string LookForTargetTypeValue(XamlContext context, out bool isExplicit, params string[] elementName)
148+
{
148149
var ancestors = context.Ancestors;
149150

150151
isExplicit = false;

src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlCodeCompletionBinding.cs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,14 @@ bool CtrlSpace(ITextEditor editor, XamlCompletionContext context)
221221
// DO NOT USE generator.CreateListForContext here!!! results in endless recursion!!!!
222222
if (context.Attribute != null) {
223223
if (!DoMarkupExtensionCompletion(context)) {
224-
var completionList = new XamlCompletionItemList(context);
225-
completionList.PreselectionLength = editor.GetWordBeforeCaretExtended().Length;
226-
if ((context.ActiveElement.Name == "Setter" || context.ActiveElement.Name == "EventSetter") && (context.Attribute.Name == "Property" || context.Attribute.Name == "Value")) {
224+
XamlCompletionItemList completionList = new XamlCompletionItemList(context);
225+
string starter = editor.GetWordBeforeCaretExtended();
226+
if (starter.Contains(".")) {
227+
completionList.PreselectionLength = starter.Length - starter.IndexOf('.') - 1;
228+
} else {
229+
completionList.PreselectionLength = starter.Length;
230+
}
231+
if ((new[] { "Setter", "EventSetter" }.Any(item => context.ActiveElement.Name == item)) && (new[] { "Property", "Value", "Event", "Handler" }.Any(item => context.Attribute.Name == item))) {
227232
DoSetterAndEventSetterCompletion(context, completionList);
228233
editor.ShowCompletionWindow(completionList);
229234
} else if ((context.ActiveElement.Name.EndsWith("Trigger", StringComparison.Ordinal) || context.ActiveElement.Name == "Condition") && context.Attribute.Name == "Value") {
@@ -239,7 +244,8 @@ bool CtrlSpace(ITextEditor editor, XamlCompletionContext context)
239244
return false;
240245
}
241246

242-
void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
247+
void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList completionList)
248+
{
243249
bool isExplicit;
244250
AttributeValue value = MarkupExtensionParser.ParseValue(Utils.LookForTargetTypeValue(context, out isExplicit, "Trigger") ?? string.Empty);
245251
string typeNameString;
@@ -273,13 +279,13 @@ void DoTriggerCompletion(XamlCompletionContext context, XamlCompletionItemList c
273279
}
274280
}
275281

276-
void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList) {
277-
bool isExplicit;
278-
string element = context.ParentElement.Name.EndsWith("Trigger", StringComparison.Ordinal) ? "Trigger" : context.ParentElement.Name;
279-
AttributeValue value = MarkupExtensionParser.ParseValue(Utils.LookForTargetTypeValue(context, out isExplicit, element) ?? string.Empty);
282+
void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlCompletionItemList completionList)
283+
{
280284
string typeNameString;
281-
var rr = resolver.ResolveAttributeValue(context, value, out typeNameString);
282-
IType typeName = rr.Type;
285+
int dotIndex;
286+
IType typeName = ResolveTargetType(context, out typeNameString, out dotIndex,
287+
string.Equals(context.Attribute.Name, "Property")
288+
|| string.Equals(context.Attribute.Name, "Event"));
283289

284290
MemberResolveResult mrr;
285291
switch (context.Attribute.Name) {
@@ -311,13 +317,23 @@ void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlComplet
311317
.Where(p => p.IsPublic && p.CanSet)
312318
.Select(prop => new XamlCompletionItem(prop))
313319
);
320+
if (dotIndex == -1) {
321+
completionList.Items.AddRange(
322+
generator.GetTypesForPropEventNameCompletion(context, true)
323+
);
324+
}
314325
break;
315326
case "Event":
316327
completionList.Items.AddRange(
317328
typeName.GetEvents()
318329
.Where(e => e.IsPublic)
319330
.Select(evt => new XamlCompletionItem(evt))
320331
);
332+
if (dotIndex == -1) {
333+
completionList.Items.AddRange(
334+
generator.GetTypesForPropEventNameCompletion(context, true)
335+
);
336+
}
321337
break;
322338
case "Handler":
323339
var loc3 = context.Editor.Document.GetLocation(XmlParser.GetActiveElementStartIndex(context.Editor.Document.Text, context.Editor.Caret.Offset));
@@ -340,6 +356,28 @@ void DoSetterAndEventSetterCompletion(XamlCompletionContext context, XamlComplet
340356
}
341357
}
342358

359+
IType ResolveTargetType(XamlCompletionContext context, out string typeName, out int dotIndex, bool isPropertyOrEventName = false)
360+
{
361+
string targetTypeValue;
362+
dotIndex = -1;
363+
if (isPropertyOrEventName && context.AttributeValue.IsString) {
364+
dotIndex = context.AttributeValue.StringValue.IndexOf('.');
365+
}
366+
if (dotIndex > 0) {
367+
targetTypeValue = context.AttributeValue.StringValue.Substring(0, dotIndex);
368+
} else {
369+
string element;
370+
bool isExplicit;
371+
if (context.ParentElement.Name.EndsWith("Trigger", StringComparison.Ordinal))
372+
element = "Trigger";
373+
else
374+
element = context.ParentElement.Name;
375+
targetTypeValue = Utils.LookForTargetTypeValue(context, out isExplicit, element);
376+
}
377+
AttributeValue value = MarkupExtensionParser.ParseValue(targetTypeValue ?? string.Empty);
378+
return resolver.ResolveAttributeValue(context, value, out typeName).Type;
379+
}
380+
343381
bool DoAttributeCompletion(XamlCompletionContext context, XamlCompletionItemList completionList)
344382
{
345383
XamlAstResolver resolver = new XamlAstResolver(compilation, context.ParseInformation);

0 commit comments

Comments
 (0)