Skip to content

Commit 1df34c2

Browse files
simonrozsivaljkurdekGitHub Actions Autoformatter
authored
Binding source generator (#21725)
* Add new public API SetBinding<TSource, TProperty> * Add source generator skeleton WIP * Setup unit tests for binding intermediate representation * Added basic nullability support * Remove unnecessary Id from the binding record * Generate casts * Split index and member access * Cleanup * Update test case * Cleanup * Fix the semantic of conditional access * add as-cast suport to source generator * improve nullability check * specify params in tests only when not default * simplify diagnostics * move path parser to separate class * small cleanup * Get nullability right in binding representation tests Co-authored-by: Šimon Rozsíval <[email protected]> * Fix path parse to work with improved tests * Integration tests (#14) * create assert extensions Co-authored-by: Šimon Rozsíval <[email protected]> * added basic binding integration test * fixed unit tests Co-authored-by: Šimon Rozsíval <[email protected]> * added cast integration test Co-authored-by: Šimon Rozsíval <[email protected]> * cleaned up tests * remove nullableEnabled param from PathParser * more clean up * Enable diagnostic generation in PathParser * refactored parse path function * further parsePath refactoring * refactored source generator utilities * fixed lambda return type nullability inference * replaced linkedList with list in ParsePath --------- Co-authored-by: Šimon Rozsíval <[email protected]> * Implement setters (#16) * Make Cast record non-nested * Simplify AccessExpressionBuilder * Add SetterBuilder * Fix BindingCodeWriter * Fix tests * Make SetterBuilder private inside Setter * Remove unnecessary IsConditional * Simplify indexes (#18) * Fix overload check (#20) * fixed correct overload check * disable test * Implement detection of writable properties (#19) * Add TODOs to change arrays to equatable arrays * Add projects to solutions * Try to run unit tests in CI * Added custom indexer support * Fix typo * Avoid allocating line separators array * Hide the new SetBinding overload from editor suggestions for now * Incremental generation tests * replaced array with equatable array * Added source information + formatting * added third party licenses * Add benchmark for source-generated SetBinding (#25) * Add benchmark for source-generated SetBinding * Auto-format source code * improve overload diagnostics tests * added more complex overload tests * improve predicate method filtering * improved diagnostics on overload detection * Auto-format source code * add ArgumentOutOfRangeException * Auto-format source code --------- Co-authored-by: GitHub Actions Autoformatter <[email protected]> Co-authored-by: Jeremi Kurdek <[email protected]> * Improve diagnostic messages * Improved incrementality testing (#28) * improved incrementality testing * added source changed test * added different file modified test * Add C-Style casts support (#26) * initialized cstyle casts * added integration and accessExpressionBuilder tests * added explicit cast to as cast adapter * Simplify inserting conditional access * Add integration tests --------- Co-authored-by: Simon Rozsival <[email protected]> * Cleanup (#29) * Improved nullable support (#30) * added unit tests for nullable disabled * added integration tests for nullable disabled * add nullable disabled support for reference types * wip: added support for nullable disabled on value types * improved integration tests * initialize support for indexers * add indexers support to SetterBuilder * added additional tests for setter builder * cleaned up SetterBuilder * Fixed nullable access with BindingTransformer Co-authored-by: Šimon Rozsíval <[email protected]> * Removed IsNullableValueType property Co-authored-by: Šimon Rozsíval <[email protected]> * Cleaned up nullability Co-authored-by: Šimon Rozsíval <[email protected]> --------- Co-authored-by: Šimon Rozsíval <[email protected]> * Simplify building setter * cleaned up methods in BindingSourceGeneratorUtilities * replaced tuples with Result<T> * simplified naming * Fix and improve unit test project * Fix bad conflict resolution in solution file --------- Co-authored-by: Jeremi Kurdek <[email protected]> Co-authored-by: Jeremi Kurdek <[email protected]> Co-authored-by: GitHub Actions Autoformatter <[email protected]>
1 parent f652001 commit 1df34c2

39 files changed

+5329
-8
lines changed

Microsoft.Maui-dev.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio Version 17
33
VisualStudioVersion = 17.0.31410.414
44
MinimumVisualStudioVersion = 10.0.40219.1
@@ -255,6 +255,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.TestCases.Mac.Test
255255
EndProject
256256
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.TestCases.WinUI.Tests", "src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj", "{A3E22F99-F380-4005-8483-3ACA6C104220}"
257257
EndProject
258+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls.BindingSourceGen", "src\Controls\src\BindingSourceGen\Controls.BindingSourceGen.csproj", "{9538341F-8A00-4356-A2B2-5C2959979F22}"
259+
EndProject
260+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls.BindingSourceGen.UnitTests", "src\Controls\tests\BindingSourceGen.UnitTests\Controls.BindingSourceGen.UnitTests.csproj", "{23FEFC89-5D2F-491C-BBE0-0E73AFD8BA47}"
261+
EndProject
258262
Global
259263
GlobalSection(SolutionConfigurationPlatforms) = preSolution
260264
Debug|Any CPU = Debug|Any CPU
@@ -648,6 +652,14 @@ Global
648652
{A3E22F99-F380-4005-8483-3ACA6C104220}.Debug|Any CPU.Build.0 = Debug|Any CPU
649653
{A3E22F99-F380-4005-8483-3ACA6C104220}.Release|Any CPU.ActiveCfg = Release|Any CPU
650654
{A3E22F99-F380-4005-8483-3ACA6C104220}.Release|Any CPU.Build.0 = Release|Any CPU
655+
{9538341F-8A00-4356-A2B2-5C2959979F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
656+
{9538341F-8A00-4356-A2B2-5C2959979F22}.Debug|Any CPU.Build.0 = Debug|Any CPU
657+
{9538341F-8A00-4356-A2B2-5C2959979F22}.Release|Any CPU.ActiveCfg = Release|Any CPU
658+
{9538341F-8A00-4356-A2B2-5C2959979F22}.Release|Any CPU.Build.0 = Release|Any CPU
659+
{23FEFC89-5D2F-491C-BBE0-0E73AFD8BA47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
660+
{23FEFC89-5D2F-491C-BBE0-0E73AFD8BA47}.Debug|Any CPU.Build.0 = Debug|Any CPU
661+
{23FEFC89-5D2F-491C-BBE0-0E73AFD8BA47}.Release|Any CPU.ActiveCfg = Release|Any CPU
662+
{23FEFC89-5D2F-491C-BBE0-0E73AFD8BA47}.Release|Any CPU.Build.0 = Release|Any CPU
651663
EndGlobalSection
652664
GlobalSection(SolutionProperties) = preSolution
653665
HideSolutionNode = FALSE
@@ -766,6 +778,8 @@ Global
766778
{5DDA6439-CDE0-4BFE-8BF9-77962BC69ACA} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
767779
{6E1ADE49-680E-4CA3-8FEA-6450802F8250} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
768780
{A3E22F99-F380-4005-8483-3ACA6C104220} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
781+
{9538341F-8A00-4356-A2B2-5C2959979F22} = {50C758FE-4E10-409A-94F5-A75480960864}
782+
{23FEFC89-5D2F-491C-BBE0-0E73AFD8BA47} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
769783
EndGlobalSection
770784
GlobalSection(ExtensibilityGlobals) = postSolution
771785
SolutionGuid = {0B8ABEAD-D2B5-4370-A187-62B5ABE4EE50}

Microsoft.Maui-vscode.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio Version 17
33
VisualStudioVersion = 17.0.31410.414
44
MinimumVisualStudioVersion = 10.0.40219.1
@@ -225,6 +225,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.TestCases.Mac.Test
225225
EndProject
226226
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.TestCases.WinUI.Tests", "src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj", "{DACF87DB-6354-4B18-A34C-923A55F317F0}"
227227
EndProject
228+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls.BindingSourceGen", "src\Controls\src\BindingSourceGen\Controls.BindingSourceGen.csproj", "{F3E4596C-3047-42F8-9724-80BCE74C141C}"
229+
EndProject
230+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls.BindingSourceGen.UnitTests", "src\Controls\tests\BindingSourceGen.UnitTests\Controls.BindingSourceGen.UnitTests.csproj", "{0048EA9A-D751-4576-A2BB-2A37BFB385A5}"
231+
EndProject
228232
Global
229233
GlobalSection(SolutionConfigurationPlatforms) = preSolution
230234
Debug|Any CPU = Debug|Any CPU
@@ -558,6 +562,14 @@ Global
558562
{DACF87DB-6354-4B18-A34C-923A55F317F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
559563
{DACF87DB-6354-4B18-A34C-923A55F317F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
560564
{DACF87DB-6354-4B18-A34C-923A55F317F0}.Release|Any CPU.Build.0 = Release|Any CPU
565+
{F3E4596C-3047-42F8-9724-80BCE74C141C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
566+
{F3E4596C-3047-42F8-9724-80BCE74C141C}.Debug|Any CPU.Build.0 = Debug|Any CPU
567+
{F3E4596C-3047-42F8-9724-80BCE74C141C}.Release|Any CPU.ActiveCfg = Release|Any CPU
568+
{F3E4596C-3047-42F8-9724-80BCE74C141C}.Release|Any CPU.Build.0 = Release|Any CPU
569+
{0048EA9A-D751-4576-A2BB-2A37BFB385A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
570+
{0048EA9A-D751-4576-A2BB-2A37BFB385A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
571+
{0048EA9A-D751-4576-A2BB-2A37BFB385A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
572+
{0048EA9A-D751-4576-A2BB-2A37BFB385A5}.Release|Any CPU.Build.0 = Release|Any CPU
561573
EndGlobalSection
562574
GlobalSection(SolutionProperties) = preSolution
563575
HideSolutionNode = FALSE
@@ -661,6 +673,8 @@ Global
661673
{AF5A8B2E-13E7-4D94-A44E-BC96180C1FCC} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
662674
{0B3AF328-82B8-431D-8AFF-45F0F86CEA0E} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
663675
{DACF87DB-6354-4B18-A34C-923A55F317F0} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
676+
{F3E4596C-3047-42F8-9724-80BCE74C141C} = {50C758FE-4E10-409A-94F5-A75480960864}
677+
{0048EA9A-D751-4576-A2BB-2A37BFB385A5} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
664678
EndGlobalSection
665679
GlobalSection(ExtensibilityGlobals) = postSolution
666680
SolutionGuid = {0B8ABEAD-D2B5-4370-A187-62B5ABE4EE50}

Microsoft.Maui.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio Version 17
33
VisualStudioVersion = 17.0.31410.414
44
MinimumVisualStudioVersion = 10.0.40219.1
@@ -275,6 +275,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.TestCases.Mac.Test
275275
EndProject
276276
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Controls.TestCases.WinUI.Tests", "src\Controls\tests\TestCases.WinUI.Tests\Controls.TestCases.WinUI.Tests.csproj", "{A1D6B9E5-D8FF-436A-9ACF-703CA5E4BD02}"
277277
EndProject
278+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls.BindingSourceGen", "src\Controls\src\BindingSourceGen\Controls.BindingSourceGen.csproj", "{83C5E677-A9C8-4E46-B72C-CAF04DC5D3D5}"
279+
EndProject
280+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Controls.BindingSourceGen.UnitTests", "src\Controls\tests\BindingSourceGen.UnitTests\Controls.BindingSourceGen.UnitTests.csproj", "{6AEE83CC-08CA-466A-BA86-774BE88A541B}"
281+
EndProject
278282
Global
279283
GlobalSection(SolutionConfigurationPlatforms) = preSolution
280284
Debug|Any CPU = Debug|Any CPU
@@ -700,6 +704,14 @@ Global
700704
{A1D6B9E5-D8FF-436A-9ACF-703CA5E4BD02}.Debug|Any CPU.Build.0 = Debug|Any CPU
701705
{A1D6B9E5-D8FF-436A-9ACF-703CA5E4BD02}.Release|Any CPU.ActiveCfg = Release|Any CPU
702706
{A1D6B9E5-D8FF-436A-9ACF-703CA5E4BD02}.Release|Any CPU.Build.0 = Release|Any CPU
707+
{83C5E677-A9C8-4E46-B72C-CAF04DC5D3D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
708+
{83C5E677-A9C8-4E46-B72C-CAF04DC5D3D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
709+
{83C5E677-A9C8-4E46-B72C-CAF04DC5D3D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
710+
{83C5E677-A9C8-4E46-B72C-CAF04DC5D3D5}.Release|Any CPU.Build.0 = Release|Any CPU
711+
{6AEE83CC-08CA-466A-BA86-774BE88A541B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
712+
{6AEE83CC-08CA-466A-BA86-774BE88A541B}.Debug|Any CPU.Build.0 = Debug|Any CPU
713+
{6AEE83CC-08CA-466A-BA86-774BE88A541B}.Release|Any CPU.ActiveCfg = Release|Any CPU
714+
{6AEE83CC-08CA-466A-BA86-774BE88A541B}.Release|Any CPU.Build.0 = Release|Any CPU
703715
EndGlobalSection
704716
GlobalSection(SolutionProperties) = preSolution
705717
HideSolutionNode = FALSE
@@ -828,6 +840,8 @@ Global
828840
{29115330-6854-4715-B382-18EA3A8A8731} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
829841
{E8CAE2B6-62B3-431C-A76D-1CCD961A1FB4} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
830842
{A1D6B9E5-D8FF-436A-9ACF-703CA5E4BD02} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
843+
{83C5E677-A9C8-4E46-B72C-CAF04DC5D3D5} = {50C758FE-4E10-409A-94F5-A75480960864}
844+
{6AEE83CC-08CA-466A-BA86-774BE88A541B} = {25D0D27A-C5FE-443D-8B65-D6C987F4A80E}
831845
EndGlobalSection
832846
GlobalSection(ExtensibilityGlobals) = postSolution
833847
SolutionGuid = {0B8ABEAD-D2B5-4370-A187-62B5ABE4EE50}

THIRD-PARTY-NOTICES.TXT

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,3 +521,63 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
521521
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
522522
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
523523
=========================================
524+
525+
526+
License notice for .NET Community Toolkit
527+
=========================================
528+
529+
(https://github.com/CommunityToolkit/dotnet/blob/main/License.md)
530+
531+
Copyright (c) .NET Foundation and Contributors
532+
533+
All rights reserved.
534+
535+
MIT License (MIT)
536+
537+
Permission is hereby granted, free of charge, to any person obtaining a copy of
538+
this software and associated documentation files (the "Software"), to deal in
539+
the Software without restriction, including without limitation the rights to
540+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
541+
the Software, and to permit persons to whom the Software is furnished to do so,
542+
subject to the following conditions:
543+
544+
The above copyright notice and this permission notice shall be included in all
545+
copies or substantial portions of the Software.
546+
547+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
548+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
549+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
550+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
551+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
552+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
553+
=========================================
554+
555+
556+
License notice for BenchmarkDotNet
557+
=========================================
558+
559+
(https://github.com/dotnet/BenchmarkDotNet/blob/master/LICENSE.md)
560+
561+
The MIT License (MIT)
562+
563+
Copyright (c) 2013–2024 .NET Foundation and contributors
564+
565+
Permission is hereby granted, free of charge, to any person obtaining
566+
a copy of this software and associated documentation files (the
567+
"Software"), to deal in the Software without restriction, including
568+
without limitation the rights to use, copy, modify, merge, publish,
569+
distribute, sublicense, and/or sell copies of the Software, and to
570+
permit persons to whom the Software is furnished to do so, subject to
571+
the following conditions:
572+
573+
The above copyright notice and this permission notice shall be
574+
included in all copies or substantial portions of the Software.
575+
576+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
577+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
578+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
579+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
580+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
581+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
582+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
583+
=========================================

eng/cake/dotnet.cake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ Task("dotnet-test")
251251
// "**/Controls.Core.Design.UnitTests.csproj",
252252
"**/Controls.Xaml.UnitTests.csproj",
253253
"**/SourceGen.UnitTests.csproj",
254+
"**/Controls.BindingSourceGen.UnitTests.csproj",
254255
"**/Core.UnitTests.csproj",
255256
"**/Essentials.UnitTests.csproj",
256257
"**/Resizetizer.UnitTests.csproj",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace Microsoft.Maui.Controls.BindingSourceGen;
2+
3+
public static class AccessExpressionBuilder
4+
{
5+
public static string ExtendExpression(string previousExpression, IPathPart nextPart)
6+
=> nextPart switch
7+
{
8+
Cast { TargetType: var targetType } => $"({previousExpression} as {CastTargetName(targetType)})",
9+
ConditionalAccess conditionalAccess => ExtendExpression(previousExpression: $"{previousExpression}?", conditionalAccess.Part),
10+
IndexAccess { Index: int numericIndex } => $"{previousExpression}[{numericIndex}]",
11+
IndexAccess { Index: string stringIndex } => $"{previousExpression}[\"{stringIndex}\"]",
12+
MemberAccess memberAccess => $"{previousExpression}.{memberAccess.MemberName}",
13+
_ => throw new NotSupportedException($"Unsupported path part type: {nextPart.GetType()}"),
14+
};
15+
16+
private static string CastTargetName(TypeDescription targetType)
17+
=> targetType.IsValueType ? $"{targetType.GlobalName}?" : targetType.GlobalName;
18+
}

0 commit comments

Comments
 (0)