Skip to content

Commit

Permalink
Merge pull request #467 from workgroupengineering/fixes/Intellisense/…
Browse files Browse the repository at this point in the history
…ControlTheme/Selector

Improve Intellisense ControlTheme compilation
  • Loading branch information
maxkatz6 authored Apr 5, 2024
2 parents f4b12db + ce75d44 commit afcb081
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -646,10 +646,19 @@ private void ProcessStyleSetter(string setterPropertyName, XmlParser state, List
}
else
{
var selector = state.FindParentAttributeValue("Selector", 1, maxLevels: 0);
var matches = Regex.Matches(selector ?? "", selectorTypes);
var types = matches.OfType<Match>().Select(m => m.Groups["type"].Value).Where(v => !string.IsNullOrEmpty(v));
selectorTypeName = types.LastOrDefault()?.Replace('|', ':') ?? "Control";
if (state.FindParentAttributeValue("Selector", 1, maxLevels: 0)?.Trim() is { Length: > 0 } selector)
{
if (selector[0]=='^')
{
selectorTypeName = state.FindParentAttributeValue("TargetType", 2, maxLevels: 0);
}
else
{
var matches = Regex.Matches(selector, selectorTypes);
var types = matches.OfType<Match>().Select(m => m.Groups["type"].Value).Where(v => !string.IsNullOrEmpty(v));
selectorTypeName = types.LastOrDefault()?.Replace('|', ':') ?? "Control";
}
}
}

if (string.IsNullOrEmpty(selectorTypeName))
Expand Down Expand Up @@ -743,7 +752,7 @@ IEnumerable<Completion> forPropertiesFromType(MetadataType? filterType, string?
{
foreach (var propertyName in MetadataHelper.FilterPropertyNames(filterType, filter, false, false))
{
yield return new Completion(propertyName, fmtInsertText?.Invoke(propertyName) ?? propertyName, propertyName, CompletionKind.DataProperty, Priority:254);
yield return new Completion(propertyName, fmtInsertText?.Invoke(propertyName) ?? propertyName, propertyName, CompletionKind.DataProperty, Priority: 254);
}
}
}
Expand Down Expand Up @@ -1027,7 +1036,7 @@ public static CompletionKind GetCompletionKindForHintValues(MetadataType type)
case SelectorStatement.FunctionArgs:
{
var fn = parser.FunctionName;
var tn = parser.TypeName;
var tn = GetFullName(parser);
var isEmptyTn = string.IsNullOrEmpty(tn);
if (previousStatement <= SelectorStatement.Middle && isEmptyTn)
{
Expand All @@ -1050,8 +1059,7 @@ public static CompletionKind GetCompletionKindForHintValues(MetadataType type)
}
else
{
var typeFullName = GetFullName(parser);
if (Helper.LookupType(typeFullName) is MetadataType { HasPseudoClasses: true } type)
if (Helper.LookupType(tn) is MetadataType { HasPseudoClasses: true } type)
{
completions.AddRange(type.PseudoClasses.Select(v => new Completion(v, CompletionKind.Selector | CompletionKind.Enum)));
}
Expand Down Expand Up @@ -1082,6 +1090,10 @@ public static CompletionKind GetCompletionKindForHintValues(MetadataType type)
if (parser.IsTemplate)
{
var ton = parser.TemplateOwner;
if (string.IsNullOrEmpty(ton))
{
ton = GetTypeFromControlTheme();
}
if (!string.IsNullOrEmpty(ton))
{
//If it hat TemplateOwner
Expand Down Expand Up @@ -1144,7 +1156,6 @@ public static CompletionKind GetCompletionKindForHintValues(MetadataType type)
}
}
}

}
}
break;
Expand Down Expand Up @@ -1259,21 +1270,25 @@ public static CompletionKind GetCompletionKindForHintValues(MetadataType type)
if (!parser.IsError)
{
parsed = (parser.LastParsedPosition ?? 0);
var parent = state.GetParentTagName(1);
// TODO: Crowling Selector operator from Attribute of the Selector
completions.Add(new Completion("^", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(">", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(".", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion("#", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":is()", ":is(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":not()", ":not(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":nth-child()", ":nth-child(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":nth-last-child()", ":nth-last-child(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion("/template/", "/template/", CompletionKind.Selector | CompletionKind.Enum));
var types = Helper.FilterTypes(default)
.Where(t => t.Value.IsAvaloniaObjectType || t.Value.HasAttachedProperties)
.Select(t => new Completion(t.Value.Name.Replace(":", "|"), CompletionKind.Class | CompletionKind.TargetTypeClass));
completions.AddRange(types);
if (!string.Equals(parent, "ControlTheme", StringComparison.OrdinalIgnoreCase))
{
completions.Add(new Completion(":", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(">", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(".", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion("#", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":is()", ":is(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":not()", ":not(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":nth-child()", ":nth-child(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion(":nth-last-child()", ":nth-last-child(", CompletionKind.Selector | CompletionKind.Enum));
completions.Add(new Completion("/template/", "/template/", CompletionKind.Selector | CompletionKind.Enum));
var types = Helper.FilterTypes(default)
.Where(t => t.Value.IsAvaloniaObjectType || t.Value.HasAttachedProperties)
.Select(t => new Completion(t.Value.Name.Replace(":", "|"), CompletionKind.Class | CompletionKind.TargetTypeClass));
completions.AddRange(types);
}
}
}
break;
Expand Down Expand Up @@ -1323,8 +1338,11 @@ public static CompletionKind GetCompletionKindForHintValues(MetadataType type)
string GetFullName(SelectorParser parser)
{
var ns = parser.Namespace;
var typename = parser.TypeName
?? GetTypeFromControlTheme();
var typename = parser.TypeName;
if (string.IsNullOrEmpty(typename))
{
typename = GetTypeFromControlTheme();
}
var typeFullName = string.IsNullOrEmpty(ns)
? typename
: $"{ns}:{typename}";
Expand Down
69 changes: 66 additions & 3 deletions tests/CompletionEngineTests/AdvancedTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Xunit;

Expand Down Expand Up @@ -487,6 +485,71 @@ public void Should_Not_Contain_Abstract_Classes()
}
}

[Fact]
public void ControlTheme_Nested_Selector_Should_Be_Completed()
{
var xaml =
"""
<UserControl.Resources>
<ControlTheme x:Key="MyButton" TargetType="Button">
<Style Selector="
""";
var compl = GetCompletionsFor(xaml).Completions;

Assert.Single(compl);
Assert.Contains(compl, v => v.InsertText == "^");
}

[Fact]
public void ControlTheme_Nested_Selector_Should_Be_Completed_PseudoClass()
{
var xaml =
"""
<UserControl.Resources>
<ControlTheme x:Key="MyButton" TargetType="Button">
<Style Selector="^:
""";
var compl = GetCompletionsFor(xaml).Completions;

Assert.Equal(10, compl.Count);
Assert.Contains(compl, v => v.InsertText == ":disabled");
}

[Fact]
public void ControlTheme_Nested_Selector_Should_Be_Completed_Template()
{
var xaml =
"""
<UserControl.Resources>
<ControlTheme x:Key="MyButton" TargetType="Button">
<Style Selector="^ /template/ C
""";
var compl = GetCompletionsFor(xaml).Completions;

Assert.Contains(compl, v => v.InsertText == "ContentPresenter");
}

[Fact]
public void ControlTheme_Nested_Selector_Should_Be_Completed_Setter()
{
string[] expected = new[]
{
"Command",
"CommandParameter",
};

var xaml =
"""
<UserControl.Resources>
<ControlTheme x:Key="MyButton" TargetType="Button">
<Style Selector="^:disabled">
<Setter Property="Com
""";
var compl = GetCompletionsFor(xaml).Completions.Select(c => c.InsertText);

Assert.Equal(expected, compl);
}

public static IEnumerable<object[]> GetStyleSelectors()
{
yield return new object[]
Expand Down Expand Up @@ -609,7 +672,7 @@ public static IEnumerable<object[]> GetStyleSelectors()
new ("AttachedBehavior","local|AttachedBehavior", Avalonia.Ide.CompletionEngine.CompletionKind.Class | Avalonia.Ide.CompletionEngine.CompletionKind.TargetTypeClass),
},
};

yield return new object[]
{
"<Style Selector=\"ToggleSwitch /template/ #",
Expand Down
5 changes: 4 additions & 1 deletion tests/CompletionEngineTests/CompletionEngineTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit afcb081

Please sign in to comment.