diff --git a/Samples.sln b/Samples.sln
index 349b0c8cd..71d51bee6 100644
--- a/Samples.sln
+++ b/Samples.sln
@@ -1,4 +1,4 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28606.18
@@ -113,9 +113,15 @@ Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "VisualBasicToCSharpConverte
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SourceGenerators", "SourceGenerators", "{14D18F51-6B59-49D5-9AB7-08B38417A459}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGeneratorSamples", "samples\CSharp\SourceGenerators\SourceGeneratorSamples\SourceGeneratorSamples.csproj", "{2ADE5CFA-5DF4-44A9-BD67-E884BCFBA045}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpSourceGeneratorSamples", "samples\CSharp\SourceGenerators\SourceGeneratorSamples\CSharpSourceGeneratorSamples.csproj", "{2ADE5CFA-5DF4-44A9-BD67-E884BCFBA045}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneratedDemo", "samples\CSharp\SourceGenerators\GeneratedDemo\GeneratedDemo.csproj", "{EC4DB63B-C2B4-4D06-AF98-15253035C6D5}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpGeneratedDemo", "samples\CSharp\SourceGenerators\GeneratedDemo\CSharpGeneratedDemo.csproj", "{EC4DB63B-C2B4-4D06-AF98-15253035C6D5}"
+EndProject
+Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "VisualBasicGeneratedDemo", "samples\VisualBasic\SourceGenerators\GeneratedDemo\VisualBasicGeneratedDemo.vbproj", "{DA924876-9CF5-47E0-AA01-ADAF47653D39}"
+EndProject
+Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "VisualBasicSourceGeneratorSamples", "samples\VisualBasic\SourceGenerators\SourceGeneratorSamples\VisualBasicSourceGeneratorSamples.vbproj", "{8322B6E4-0CB1-4EC1-A2CC-2E4DB02C834A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SourceGenerators", "SourceGenerators", "{E79B07C8-0859-4B5C-9650-68D855833C6E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -283,6 +289,14 @@ Global
{EC4DB63B-C2B4-4D06-AF98-15253035C6D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EC4DB63B-C2B4-4D06-AF98-15253035C6D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EC4DB63B-C2B4-4D06-AF98-15253035C6D5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DA924876-9CF5-47E0-AA01-ADAF47653D39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA924876-9CF5-47E0-AA01-ADAF47653D39}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DA924876-9CF5-47E0-AA01-ADAF47653D39}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DA924876-9CF5-47E0-AA01-ADAF47653D39}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8322B6E4-0CB1-4EC1-A2CC-2E4DB02C834A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8322B6E4-0CB1-4EC1-A2CC-2E4DB02C834A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8322B6E4-0CB1-4EC1-A2CC-2E4DB02C834A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8322B6E4-0CB1-4EC1-A2CC-2E4DB02C834A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -342,6 +356,9 @@ Global
{14D18F51-6B59-49D5-9AB7-08B38417A459} = {C3FB27E9-C8EE-4F76-B0AA-7CD67A7E652B}
{2ADE5CFA-5DF4-44A9-BD67-E884BCFBA045} = {14D18F51-6B59-49D5-9AB7-08B38417A459}
{EC4DB63B-C2B4-4D06-AF98-15253035C6D5} = {14D18F51-6B59-49D5-9AB7-08B38417A459}
+ {DA924876-9CF5-47E0-AA01-ADAF47653D39} = {E79B07C8-0859-4B5C-9650-68D855833C6E}
+ {8322B6E4-0CB1-4EC1-A2CC-2E4DB02C834A} = {E79B07C8-0859-4B5C-9650-68D855833C6E}
+ {E79B07C8-0859-4B5C-9650-68D855833C6E} = {CDA94F62-E35A-4913-8045-D9D42416513C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B849838B-3D7A-4B6B-BE07-285DCB1588F4}
diff --git a/samples/CSharp/SourceGenerators/GeneratedDemo/GeneratedDemo.csproj b/samples/CSharp/SourceGenerators/GeneratedDemo/CSharpGeneratedDemo.csproj
similarity index 82%
rename from samples/CSharp/SourceGenerators/GeneratedDemo/GeneratedDemo.csproj
rename to samples/CSharp/SourceGenerators/GeneratedDemo/CSharpGeneratedDemo.csproj
index b95bde39c..4b3054e9f 100644
--- a/samples/CSharp/SourceGenerators/GeneratedDemo/GeneratedDemo.csproj
+++ b/samples/CSharp/SourceGenerators/GeneratedDemo/CSharpGeneratedDemo.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/samples/CSharp/SourceGenerators/SourceGeneratorSamples/SourceGeneratorSamples.csproj b/samples/CSharp/SourceGenerators/SourceGeneratorSamples/CSharpSourceGeneratorSamples.csproj
similarity index 100%
rename from samples/CSharp/SourceGenerators/SourceGeneratorSamples/SourceGeneratorSamples.csproj
rename to samples/CSharp/SourceGenerators/SourceGeneratorSamples/CSharpSourceGeneratorSamples.csproj
diff --git a/samples/VisualBasic/SourceGenerators/GeneratedDemo/Program.vb b/samples/VisualBasic/SourceGenerators/GeneratedDemo/Program.vb
index 154f716e0..fd209d06b 100644
--- a/samples/VisualBasic/SourceGenerators/GeneratedDemo/Program.vb
+++ b/samples/VisualBasic/SourceGenerators/GeneratedDemo/Program.vb
@@ -4,36 +4,30 @@ Option Infer On
Module Program
- Public Sub Main()
+ Public Sub Main()
- Console.WriteLine("Running HelloWorld:
+ Console.WriteLine("Running HelloWorld:
")
- UseHelloWorldGenerator.Run()
+ UseHelloWorldGenerator.Run()
- Console.WriteLine("
+ Console.WriteLine("
Running AutoNotify:
")
- UseAutoNotifyGenerator.Run()
+ UseAutoNotifyGenerator.Run()
- Console.WriteLine("
+ Console.WriteLine("
Running XmlSettings:
")
- UseXmlSettingsGenerator.Run()
+ UseXmlSettingsGenerator.Run()
- Console.WriteLine("
+ Console.WriteLine("
Running CsvGenerator:
")
- UseCsvGenerator.Run()
+ UseCsvGenerator.Run()
- Console.WriteLine("
+ End Sub
-Running MustacheGenerator:
-")
- UseMustacheGenerator.Run()
-
- End Sub
-
-End Module
\ No newline at end of file
+End Module
diff --git a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseAutoNotifyGenerator.vb b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseAutoNotifyGenerator.vb
index ea1a1a3d8..f810bd4a6 100644
--- a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseAutoNotifyGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseAutoNotifyGenerator.vb
@@ -7,36 +7,36 @@ Imports AutoNotify
' The view model we'd like to augment
Partial Public Class ExampleViewModel
-
- Private _text As String = "private field text"
+
+ Private _text As String = "private field text"
-
- Private _amount As Integer = 5
+
+ Private _amount As Integer = 5
End Class
Public Module UseAutoNotifyGenerator
- Public Sub Run()
+ Public Sub Run()
- Dim vm As New ExampleViewModel()
+ Dim vm As New ExampleViewModel()
- ' we didn't explicitly create the 'Text' property, it was generated for us
- Dim text = vm.Text
- Console.WriteLine($"Text = {text}")
+ ' we didn't explicitly create the 'Text' property, it was generated for us
+ Dim text = vm.Text
+ Console.WriteLine($"Text = {text}")
- ' Properties can have differnt names generated based on the PropertyName argument of the attribute
- Dim count = vm.Count
- Console.WriteLine($"Count = {count}")
+ ' Properties can have differnt names generated based on the PropertyName argument of the attribute
+ Dim count = vm.Count
+ Console.WriteLine($"Count = {count}")
- ' the viewmodel will automatically implement INotifyPropertyChanged
- AddHandler vm.PropertyChanged, Sub(o, e) Console.WriteLine($"Property {e.PropertyName} was changed")
- vm.Text = "abc"
- vm.Count = 123
+ ' the viewmodel will automatically implement INotifyPropertyChanged
+ AddHandler vm.PropertyChanged, Sub(o, e) Console.WriteLine($"Property {e.PropertyName} was changed")
+ vm.Text = "abc"
+ vm.Count = 123
- ' Try adding fields to the ExampleViewModel class above and tagging them with the attribute
- ' You'll see the matching generated properties visibile in IntelliSense in realtime
+ ' Try adding fields to the ExampleViewModel class above and tagging them with the attribute
+ ' You'll see the matching generated properties visibile in IntelliSense in realtime
- End Sub
+ End Sub
-End Module
\ No newline at end of file
+End Module
diff --git a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseCsvGenerator.vb b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseCsvGenerator.vb
index 78c199326..f4c055835 100644
--- a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseCsvGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseCsvGenerator.vb
@@ -6,13 +6,13 @@ Imports CSV
Friend Class UseCsvGenerator
- Public Shared Sub Run()
+ Public Shared Sub Run()
- Console.WriteLine("## CARS")
- Cars.All.ToList().ForEach(Sub(c) Console.WriteLine(c.Brand & vbTab & c.Model & vbTab & c.Year & vbTab & c.Cc & vbTab & c.Favorite))
- Console.WriteLine(vbCr & "## PEOPLE")
- People.All.ToList().ForEach(Sub(p) Console.WriteLine(p.Name & vbTab & p.Address & vbTab & p._11Age))
+ Console.WriteLine("## CARS")
+ Cars.All.ToList().ForEach(Sub(c) Console.WriteLine(c.Brand & vbTab & c.Model & vbTab & c.Year & vbTab & c.Cc & vbTab & c.Favorite))
+ Console.WriteLine(vbCr & "## PEOPLE")
+ People.All.ToList().ForEach(Sub(p) Console.WriteLine(p.Name & vbTab & p.Address & vbTab & p._11Age))
- End Sub
+ End Sub
-End Class
\ No newline at end of file
+End Class
diff --git a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseHelloWorldGenerator.vb b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseHelloWorldGenerator.vb
index 78a173ca7..89fa11b47 100644
--- a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseHelloWorldGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseHelloWorldGenerator.vb
@@ -1,8 +1,8 @@
Public Module UseHelloWorldGenerator
- Public Sub Run()
- ' The static call below is generated at build time, and will list the syntax trees used in the compilation
- HelloWorldGenerated.HelloWorld.SayHello()
- End Sub
+ Public Sub Run()
+ ' The static call below is generated at build time, and will list the syntax trees used in the compilation
+ HelloWorldGenerated.HelloWorld.SayHello()
+ End Sub
End Module
diff --git a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseMustacheGenerator.vb b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseMustacheGenerator.vb
deleted file mode 100644
index 3c9a97c41..000000000
--- a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseMustacheGenerator.vb
+++ /dev/null
@@ -1,94 +0,0 @@
-Option Explicit On
-Option Strict On
-Option Infer On
-
-Imports GeneratedDemo.UseMustacheGenerator
-
-
-
-
-
-
-
-Friend Class UseMustacheGenerator
-
- Public Shared Sub Run()
- Console.WriteLine(Mustache.Constants.Lottery)
- Console.WriteLine(Mustache.Constants.HR)
- Console.WriteLine(Mustache.Constants.HTML)
- Console.WriteLine(Mustache.Constants.Section)
- Console.WriteLine(Mustache.Constants.NestedSection)
- End Sub
-
- ' Mustache templates and hashes from the manual at https://mustache.github.io/mustache.1.html...
- Public Const t1 As String = "
-Hello {{name}}
-You have just won {{value}} dollars!
-{{#in_ca}}
-Well, {{taxed_value}} dollars, after taxes.
-{{/in_ca}}
-"
- Public Const h1 As String = "
-{
- ""name"": ""Chris"",
- ""value"": 10000,
- ""taxed_value"": 5000,
- ""in_ca"": true
-}
-"
- Public Const t2 As String = "
-* {{name}}
-* {{age}}
-* {{company}}
-* {{{company}}}
-"
- Public Const h2 As String = "
-{
- ""name"": ""Chris"",
- ""company"": ""GitHub""
-}
-"
- Public Const t3 As String = "
- Shown
- {{#person}}
- Never shown!
- {{/person}}
- "
- Public Const h3 As String = "
-{
- ""person"": false
-}
-"
- Public Const t4 As String = "
-{{#repo}}
- {{name}}
-{{/repo}}
-"
- Public Const h4 As String = "
-{
- ""repo"": [
- { ""name"": ""resque"" },
- { ""name"": ""hub"" },
- { ""name"": ""rip"" }
- ]
-}
-"
- Public Const t5 As String = "
-{{#repo}}
- {{name}}
- {{#nested}}
- NestedName: {{name}}
- {{/nested}}
-{{/repo}}
-"
- Public Const h5 As String = "
-{
- ""repo"": [
- { ""name"": ""resque"", ""nested"":[{""name"":""nestedResque""}] },
- { ""name"": ""hub"" },
- { ""name"": ""rip"" }
- ]
-}
-"
-
-End Class
\ No newline at end of file
diff --git a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseXmlSettingsGenerator.vb b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseXmlSettingsGenerator.vb
index 0ace59e74..eb9a8e730 100644
--- a/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseXmlSettingsGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/GeneratedDemo/UseXmlSettingsGenerator.vb
@@ -2,24 +2,24 @@
Public Module UseXmlSettingsGenerator
- Public Sub Run()
+ Public Sub Run()
- ' This XmlSettings generator makes a static property in the XmlSettings class for each .xmlsettings file
+ ' This XmlSettings generator makes a static property in the XmlSettings class for each .xmlsettings file
- ' here we have the 'Main' settings file from MainSettings.xmlsettings
- ' the name is determined by the 'name' attribute of the root settings element
- Dim main As XmlSettings.MainSettings = XmlSettings.Main
- Console.WriteLine($"Reading settings from {main.GetLocation()}")
+ ' here we have the 'Main' settings file from MainSettings.xmlsettings
+ ' the name is determined by the 'name' attribute of the root settings element
+ Dim main As XmlSettings.MainSettings = XmlSettings.Main
+ Console.WriteLine($"Reading settings from {main.GetLocation()}")
- ' settings are strongly typed and can be read directly from the static instance
- Dim firstRun As Boolean = XmlSettings.Main.FirstRun
- Console.WriteLine($"Setting firstRun = {firstRun}")
+ ' settings are strongly typed and can be read directly from the static instance
+ Dim firstRun As Boolean = XmlSettings.Main.FirstRun
+ Console.WriteLine($"Setting firstRun = {firstRun}")
- Dim cacheSize As Integer = XmlSettings.Main.CacheSize
- Console.WriteLine($"Setting cacheSize = {cacheSize}")
+ Dim cacheSize As Integer = XmlSettings.Main.CacheSize
+ Console.WriteLine($"Setting cacheSize = {cacheSize}")
- ' Try adding some keys to the settings file and see the settings become available to read from
+ ' Try adding some keys to the settings file and see the settings become available to read from
- End Sub
+ End Sub
-End Module
\ No newline at end of file
+End Module
diff --git a/samples/VisualBasic/SourceGenerators/GeneratedDemo/GeneratedDemo.vbproj b/samples/VisualBasic/SourceGenerators/GeneratedDemo/VisualBasicGeneratedDemo.vbproj
similarity index 84%
rename from samples/VisualBasic/SourceGenerators/GeneratedDemo/GeneratedDemo.vbproj
rename to samples/VisualBasic/SourceGenerators/GeneratedDemo/VisualBasicGeneratedDemo.vbproj
index 08120ed6f..6df6a390c 100644
--- a/samples/VisualBasic/SourceGenerators/GeneratedDemo/GeneratedDemo.vbproj
+++ b/samples/VisualBasic/SourceGenerators/GeneratedDemo/VisualBasicGeneratedDemo.vbproj
@@ -14,7 +14,7 @@
-
+
diff --git a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/AutoNotifyGenerator.vb b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/AutoNotifyGenerator.vb
index 981ae965d..4c1ca4af8 100644
--- a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/AutoNotifyGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/AutoNotifyGenerator.vb
@@ -1,4 +1,4 @@
-Option Explicit On
+Option Explicit On
Option Infer On
Option Strict On
@@ -11,11 +11,11 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace SourceGeneratorSamples
-
- Public Class AutoNotifyGenerator
- Implements ISourceGenerator
+
+ Public Class AutoNotifyGenerator
+ Implements ISourceGenerator
- Private Const ATTRIBUTE_TEXT As String = "
+ Private Const ATTRIBUTE_TEXT As String = "
Imports System
Namespace Global.AutoNotify
@@ -31,68 +31,68 @@ Namespace Global.AutoNotify
End Namespace
"
- Public Sub Initialize(context As GeneratorInitializationContext) Implements ISourceGenerator.Initialize
- ' Register a syntax receiver that will be created for each generation pass
- context.RegisterForSyntaxNotifications(Function() As ISyntaxReceiver
- Return New SyntaxReceiver
- End Function)
- End Sub
-
- Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
-
- ' add the attribute text
- context.AddSource("AutoNotifyAttribute", SourceText.From(ATTRIBUTE_TEXT, Encoding.UTF8))
-
- ' retreive the populated receiver
- Dim tempVar = TypeOf context.SyntaxReceiver Is SyntaxReceiver
- Dim receiver = TryCast(context.SyntaxReceiver, SyntaxReceiver)
- If Not tempVar Then
- Return
- End If
-
- ' we're going to create a new compilation that contains the attribute.
- ' TODO: we should allow source generators to provide source during initialize, so that this step isn't required.
- Dim options1 = context.Compilation.SyntaxTrees.First().Options
- Dim compilation1 = context.Compilation.AddSyntaxTrees(VisualBasicSyntaxTree.ParseText(SourceText.From(ATTRIBUTE_TEXT, Encoding.UTF8), CType(options1, VisualBasicParseOptions)))
-
- ' get the newly bound attribute, and INotifyPropertyChanged
- Dim attributeSymbol = compilation1.GetTypeByMetadataName("AutoNotify.AutoNotifyAttribute")
- Dim notifySymbol = compilation1.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged")
-
- ' loop over the candidate fields, and keep the ones that are actually annotated
- Dim fieldSymbols As New List(Of IFieldSymbol)
-
- For Each field In receiver.CandidateFields
- Dim model = compilation1.GetSemanticModel(field.SyntaxTree)
- For Each variable In field.Declarators
- For Each name In variable.Names
- ' Get the symbol being decleared by the field, and keep it if its annotated
- Dim fieldSymbol = TryCast(model.GetDeclaredSymbol(name), IFieldSymbol)
- If fieldSymbol.GetAttributes().Any(Function(ad) ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.[Default])) Then
- fieldSymbols.Add(fieldSymbol)
+ Public Sub Initialize(context As GeneratorInitializationContext) Implements ISourceGenerator.Initialize
+ ' Register a syntax receiver that will be created for each generation pass
+ context.RegisterForSyntaxNotifications(Function() As ISyntaxReceiver
+ Return New SyntaxReceiver
+ End Function)
+ End Sub
+
+ Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
+
+ ' add the attribute text
+ context.AddSource("AutoNotifyAttribute", SourceText.From(ATTRIBUTE_TEXT, Encoding.UTF8))
+
+ ' retreive the populated receiver
+ Dim tempVar = TypeOf context.SyntaxReceiver Is SyntaxReceiver
+ Dim receiver = TryCast(context.SyntaxReceiver, SyntaxReceiver)
+ If Not tempVar Then
+ Return
End If
- Next
- Next
- Next
- ' group the fields by class, and generate the source
- For Each group In fieldSymbols.GroupBy(Function(f) f.ContainingType)
- Dim classSource = ProcessClass(group.Key, group.ToList(), attributeSymbol, notifySymbol)
- context.AddSource($"{group.Key.Name}_AutoNotify.vb", SourceText.From(classSource, Encoding.UTF8))
- Next
+ ' we're going to create a new compilation that contains the attribute.
+ ' TODO: we should allow source generators to provide source during initialize, so that this step isn't required.
+ Dim options1 = context.Compilation.SyntaxTrees.First().Options
+ Dim compilation1 = context.Compilation.AddSyntaxTrees(VisualBasicSyntaxTree.ParseText(SourceText.From(ATTRIBUTE_TEXT, Encoding.UTF8), CType(options1, VisualBasicParseOptions)))
+
+ ' get the newly bound attribute, and INotifyPropertyChanged
+ Dim attributeSymbol = compilation1.GetTypeByMetadataName("AutoNotify.AutoNotifyAttribute")
+ Dim notifySymbol = compilation1.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged")
+
+ ' loop over the candidate fields, and keep the ones that are actually annotated
+ Dim fieldSymbols As New List(Of IFieldSymbol)
+
+ For Each field In receiver.CandidateFields
+ Dim model = compilation1.GetSemanticModel(field.SyntaxTree)
+ For Each variable In field.Declarators
+ For Each name In variable.Names
+ ' Get the symbol being decleared by the field, and keep it if its annotated
+ Dim fieldSymbol = TryCast(model.GetDeclaredSymbol(name), IFieldSymbol)
+ If fieldSymbol.GetAttributes().Any(Function(ad) ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.[Default])) Then
+ fieldSymbols.Add(fieldSymbol)
+ End If
+ Next
+ Next
+ Next
+
+ ' group the fields by class, and generate the source
+ For Each group In fieldSymbols.GroupBy(Function(f) f.ContainingType, SymbolEqualityComparer.Default)
+ Dim classSource = ProcessClass(CType(group.Key, INamedTypeSymbol), group.ToList(), attributeSymbol, notifySymbol)
+ context.AddSource($"{group.Key.Name}_AutoNotify.vb", SourceText.From(classSource, Encoding.UTF8))
+ Next
- End Sub
+ End Sub
- Private Function ProcessClass(classSymbol As INamedTypeSymbol, fields As List(Of IFieldSymbol), attributeSymbol As ISymbol, notifySymbol As ISymbol) As String
+ Private Function ProcessClass(classSymbol As INamedTypeSymbol, fields As List(Of IFieldSymbol), attributeSymbol As ISymbol, notifySymbol As ISymbol) As String
- If Not classSymbol.ContainingSymbol.Equals(classSymbol.ContainingNamespace, SymbolEqualityComparer.[Default]) Then
- Return Nothing 'TODO: issue a diagnostic that it must be top level
- End If
+ If Not classSymbol.ContainingSymbol.Equals(classSymbol.ContainingNamespace, SymbolEqualityComparer.[Default]) Then
+ Return Nothing 'TODO: issue a diagnostic that it must be top level
+ End If
- Dim namespaceName = classSymbol.ContainingNamespace.ToDisplayString()
+ Dim namespaceName = classSymbol.ContainingNamespace.ToDisplayString()
- ' begin building the generated source
- Dim source = New StringBuilder($"Option Explicit On
+ ' begin building the generated source
+ Dim source = New StringBuilder($"Option Explicit On
Option Strict On
Option Infer On
@@ -103,63 +103,63 @@ Namespace Global.{namespaceName}
")
- ' if the class doesn't implement INotifyPropertyChanged already, add it
- If Not classSymbol.Interfaces.Contains(CType(notifySymbol, INamedTypeSymbol)) Then
- source.Append(" Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
+ ' if the class doesn't implement INotifyPropertyChanged already, add it
+ If Not classSymbol.Interfaces.Contains(CType(notifySymbol, INamedTypeSymbol)) Then
+ source.Append(" Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
")
- End If
+ End If
- ' create properties for each field
- For Each fieldSymbol In fields
- ProcessField(source, fieldSymbol, attributeSymbol)
- Next
+ ' create properties for each field
+ For Each fieldSymbol In fields
+ ProcessField(source, fieldSymbol, attributeSymbol)
+ Next
- source.Append("
+ source.Append("
End Class
End Namespace")
- Return source.ToString()
+ Return source.ToString()
- End Function
+ End Function
- Private Sub ProcessField(source As StringBuilder, fieldSymbol As IFieldSymbol, attributeSymbol As ISymbol)
+ Private Sub ProcessField(source As StringBuilder, fieldSymbol As IFieldSymbol, attributeSymbol As ISymbol)
- Dim chooseName As Func(Of String, TypedConstant, String) =
+ Dim chooseName As Func(Of String, TypedConstant, String) =
Function(fieldName1 As String, overridenNameOpt1 As TypedConstant) As String
- If Not overridenNameOpt1.IsNull Then
- Return overridenNameOpt1.Value.ToString()
- End If
+ If Not overridenNameOpt1.IsNull Then
+ Return overridenNameOpt1.Value.ToString()
+ End If
- fieldName1 = fieldName1.TrimStart("_"c)
- If fieldName1.Length = 0 Then
- Return String.Empty
- End If
+ fieldName1 = fieldName1.TrimStart("_"c)
+ If fieldName1.Length = 0 Then
+ Return String.Empty
+ End If
- If fieldName1.Length = 1 Then
- Return fieldName1.ToUpper()
- End If
+ If fieldName1.Length = 1 Then
+ Return fieldName1.ToUpper()
+ End If
- Return fieldName1.Substring(0, 1).ToUpper() & fieldName1.Substring(1)
+ Return fieldName1.Substring(0, 1).ToUpper() & fieldName1.Substring(1)
End Function
- ' get the name and type of the field
- Dim fieldName = fieldSymbol.Name
- Dim fieldType = fieldSymbol.Type
+ ' get the name and type of the field
+ Dim fieldName = fieldSymbol.Name
+ Dim fieldType = fieldSymbol.Type
- ' get the AutoNotify attribute from the field, and any associated data
- Dim attributeData = fieldSymbol.GetAttributes().[Single](Function(ad) ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.[Default]))
- Dim overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(Function(kvp) kvp.Key = "PropertyName").Value
+ ' get the AutoNotify attribute from the field, and any associated data
+ Dim attributeData = fieldSymbol.GetAttributes().[Single](Function(ad) ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.[Default]))
+ Dim overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(Function(kvp) kvp.Key = "PropertyName").Value
- Dim propertyName = chooseName(fieldName, overridenNameOpt)
- If propertyName.Length = 0 OrElse propertyName = fieldName Then
- 'TODO: issue a diagnostic that we can't process this field
- Return
- End If
+ Dim propertyName = chooseName(fieldName, overridenNameOpt)
+ If propertyName.Length = 0 OrElse propertyName = fieldName Then
+ 'TODO: issue a diagnostic that we can't process this field
+ Return
+ End If
- source.Append($"
+ source.Append($"
Public Property {propertyName} As {fieldType}
Get
Return Me.{fieldName}
@@ -171,31 +171,31 @@ End Namespace")
End Property
")
- End Sub
-
- '''
- ''' Created on demand before each generation pass
- '''
- Class SyntaxReceiver
- Implements ISyntaxReceiver
-
- Public ReadOnly Property CandidateFields As List(Of FieldDeclarationSyntax) = New List(Of FieldDeclarationSyntax)
-
- '''
- ''' Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation
- '''
- Public Sub OnVisitSyntaxNode(syntaxNode As SyntaxNode) Implements ISyntaxReceiver.OnVisitSyntaxNode
- ' any field with at least one attribute is a candidate for property generation
- If TypeOf syntaxNode Is FieldDeclarationSyntax Then
- Dim fieldDeclarationSyntax = TryCast(syntaxNode, FieldDeclarationSyntax)
- If fieldDeclarationSyntax.AttributeLists.Count > 0 Then
- CandidateFields.Add(fieldDeclarationSyntax)
- End If
- End If
- End Sub
+ End Sub
+
+ '''
+ ''' Created on demand before each generation pass
+ '''
+ Class SyntaxReceiver
+ Implements ISyntaxReceiver
+
+ Public ReadOnly Property CandidateFields As List(Of FieldDeclarationSyntax) = New List(Of FieldDeclarationSyntax)
+
+ '''
+ ''' Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation
+ '''
+ Public Sub OnVisitSyntaxNode(syntaxNode As SyntaxNode) Implements ISyntaxReceiver.OnVisitSyntaxNode
+ ' any field with at least one attribute is a candidate for property generation
+ If TypeOf syntaxNode Is FieldDeclarationSyntax Then
+ Dim fieldDeclarationSyntax = TryCast(syntaxNode, FieldDeclarationSyntax)
+ If fieldDeclarationSyntax.AttributeLists.Count > 0 Then
+ CandidateFields.Add(fieldDeclarationSyntax)
+ End If
+ End If
+ End Sub
+
+ End Class
End Class
- End Class
-
-End Namespace
\ No newline at end of file
+End Namespace
diff --git a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/CsvGenerator.vb b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/CsvGenerator.vb
index d474fdca2..fa7d13b90 100644
--- a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/CsvGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/CsvGenerator.vb
@@ -14,72 +14,72 @@ Imports NotVisualBasic.FileIO
Namespace SourceGeneratorSamples
-
- Public Class CsvGenerator
- Implements ISourceGenerator
-
- Public Enum CsvLoadType
- Startup
- OnDemand
- End Enum
-
- Public Sub Initialize(context As GeneratorInitializationContext) Implements Microsoft.CodeAnalysis.ISourceGenerator.Initialize
-
- End Sub
-
- Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
- Dim options As IEnumerable(Of (CsvLoadType, Boolean, AdditionalText)) = GetLoadOptions(context)
- Dim nameCodeSequence As IEnumerable(Of (Name As String, Code As String)) = SourceFilesFromAdditionalFiles(options)
- For Each entry In nameCodeSequence
- context.AddSource($"Csv_{entry.Name}", SourceText.From(entry.Code, Encoding.UTF8))
- Next
- End Sub
-
- ' Guesses type of property for the object from the value of a csv field
- Public Shared Function GetCsvFieldType(exemplar As String) As String
- Dim garbageBoolean As Boolean
- Dim garbageInteger As Integer
- Dim garbageDouble As Double
- Select Case True
- Case Boolean.TryParse(exemplar, garbageBoolean) : Return "Boolean"
- Case Integer.TryParse(exemplar, garbageInteger) : Return "Integer"
- Case Double.TryParse(exemplar, garbageDouble) : Return "Double"
- Case Else : Return "String"
- End Select
- End Function
-
- ' Examines the header row and the first row in the csv file to gather all header types and names
- ' Also it returns the first row of data, because it must be read to figure out the types,
- ' As the CsvTextFieldParser cannot 'Peek' ahead of one line. If there is no first line,
- ' it consider all properties as strings. The generator returns an empty list of properly
- ' typed objects in such case. If the file is completely empty, an error is generated.
- Public Shared Function ExtractProperties(parser As CsvTextFieldParser) As (Types As String(), Names As String(), Fields As String())
-
- Dim headerFields = parser.ReadFields()
- If headerFields Is Nothing Then
- Throw New Exception("Empty csv file!")
- End If
-
- Dim firstLineFields = parser.ReadFields()
- If firstLineFields Is Nothing Then
- Return (Enumerable.Repeat("String", headerFields.Length).ToArray(), headerFields, firstLineFields)
- Else
- Return (firstLineFields.[Select](Function(field) GetCsvFieldType(field)).ToArray(), headerFields.[Select](New Func(Of String, String)(AddressOf StringToValidPropertyName)).ToArray(), firstLineFields)
- End If
-
- End Function
-
- ' Adds a class to the `CSV` namespace for each `csv` file passed in. The class has a static property
- ' named `All` that returns the list of strongly typed objects generated on demand at first access.
- ' There is the slight chance of a race condition in a multi-thread program, but the result is relatively benign
- ' , loading the collection multiple times instead of once. Measures could be taken to avoid that.
- Public Shared Function GenerateClassFile(className As String, csvText As String, loadTime As CsvLoadType, cacheObjects As Boolean) As String
-
- Dim sb As New StringBuilder
- Dim parser As New CsvTextFieldParser(New StringReader(csvText))
-
- ''' Imports
- sb.Append("Option Explicit On
+
+ Public Class CsvGenerator
+ Implements ISourceGenerator
+
+ Public Enum CsvLoadType
+ Startup
+ OnDemand
+ End Enum
+
+ Public Sub Initialize(context As GeneratorInitializationContext) Implements Microsoft.CodeAnalysis.ISourceGenerator.Initialize
+
+ End Sub
+
+ Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
+ Dim options As IEnumerable(Of (CsvLoadType, Boolean, AdditionalText)) = GetLoadOptions(context)
+ Dim nameCodeSequence As IEnumerable(Of (Name As String, Code As String)) = SourceFilesFromAdditionalFiles(options)
+ For Each entry In nameCodeSequence
+ context.AddSource($"Csv_{entry.Name}", SourceText.From(entry.Code, Encoding.UTF8))
+ Next
+ End Sub
+
+ ' Guesses type of property for the object from the value of a csv field
+ Public Shared Function GetCsvFieldType(exemplar As String) As String
+ Dim garbageBoolean As Boolean
+ Dim garbageInteger As Integer
+ Dim garbageDouble As Double
+ Select Case True
+ Case Boolean.TryParse(exemplar, garbageBoolean) : Return "Boolean"
+ Case Integer.TryParse(exemplar, garbageInteger) : Return "Integer"
+ Case Double.TryParse(exemplar, garbageDouble) : Return "Double"
+ Case Else : Return "String"
+ End Select
+ End Function
+
+ ' Examines the header row and the first row in the csv file to gather all header types and names
+ ' Also it returns the first row of data, because it must be read to figure out the types,
+ ' As the CsvTextFieldParser cannot 'Peek' ahead of one line. If there is no first line,
+ ' it consider all properties as strings. The generator returns an empty list of properly
+ ' typed objects in such case. If the file is completely empty, an error is generated.
+ Public Shared Function ExtractProperties(parser As CsvTextFieldParser) As (Types As String(), Names As String(), Fields As String())
+
+ Dim headerFields = parser.ReadFields()
+ If headerFields Is Nothing Then
+ Throw New Exception("Empty csv file!")
+ End If
+
+ Dim firstLineFields = parser.ReadFields()
+ If firstLineFields Is Nothing Then
+ Return (Enumerable.Repeat("String", headerFields.Length).ToArray(), headerFields, firstLineFields)
+ Else
+ Return (firstLineFields.[Select](Function(field) GetCsvFieldType(field)).ToArray(), headerFields.[Select](New Func(Of String, String)(AddressOf StringToValidPropertyName)).ToArray(), firstLineFields)
+ End If
+
+ End Function
+
+ ' Adds a class to the `CSV` namespace for each `csv` file passed in. The class has a static property
+ ' named `All` that returns the list of strongly typed objects generated on demand at first access.
+ ' There is the slight chance of a race condition in a multi-thread program, but the result is relatively benign
+ ' , loading the collection multiple times instead of once. Measures could be taken to avoid that.
+ Public Shared Function GenerateClassFile(className As String, csvText As String, loadTime As CsvLoadType, cacheObjects As Boolean) As String
+
+ Dim sb As New StringBuilder
+ Dim parser As New CsvTextFieldParser(New StringReader(csvText))
+
+ ''' Imports
+ sb.Append("Option Explicit On
Option Strict On
Option Infer On
@@ -88,121 +88,121 @@ Imports System.Collections.Generic
Namespace Global.CSV
")
- ''' Class Definition
- sb.Append($"
+ ''' Class Definition
+ sb.Append($"
Public Class {className}
")
- If loadTime = CsvLoadType.Startup Then
- sb.Append($" Shared Sub New()
+ If loadTime = CsvLoadType.Startup Then
+ sb.Append($" Shared Sub New()
Dim x = All
End Sub
")
- End If
+ End If
- Dim tupleTemp = ExtractProperties(parser) : Dim types = tupleTemp.Types, names = tupleTemp.Names, fields = tupleTemp.Fields
- Dim minLen = Math.Min(types.Length, names.Length)
+ Dim tupleTemp = ExtractProperties(parser) : Dim types = tupleTemp.Types, names = tupleTemp.Names, fields = tupleTemp.Fields
+ Dim minLen = Math.Min(types.Length, names.Length)
- For i = 0 To minLen - 1
- sb.AppendLine($" Public Property {StringToValidPropertyName(names(i))} As {types(i)}")
- Next
+ For i = 0 To minLen - 1
+ sb.AppendLine($" Public Property {StringToValidPropertyName(names(i))} As {types(i)}")
+ Next
- ''' Loading data
- sb.Append($"
+ ''' Loading data
+ sb.Append($"
Private Shared m_all As IEnumerable(Of {className})
Public Shared ReadOnly Property All As IEnumerable(Of {className})
Get
")
- If cacheObjects Then
- sb.Append(" If m_all IsNot Nothing Then
+ If cacheObjects Then
+ sb.Append(" If m_all IsNot Nothing Then
Return m_all
End If
")
- End If
+ End If
- sb.Append($" Dim l As New List(Of {className})()
+ sb.Append($" Dim l As New List(Of {className})()
Dim c As {className}
")
- Do
+ Do
- If fields Is Nothing Then
- Continue Do
- End If
- If fields.Length < minLen Then
- Throw New Exception("Not enough fields in CSV file.")
- End If
+ If fields Is Nothing Then
+ Continue Do
+ End If
+ If fields.Length < minLen Then
+ Throw New Exception("Not enough fields in CSV file.")
+ End If
- sb.AppendLine($" c = New {className}()")
+ sb.AppendLine($" c = New {className}()")
- Dim value As String '= ""
- For i As Integer = 0 To minLen - 1
- ' Wrap strings in quotes.
- value = If(GetCsvFieldType(fields(i)) = "String", $"""{fields(i).Trim().Trim(New Char() {""""c})}""", fields(i))
- sb.AppendLine($" c.{names(i)} = {value}")
- Next
+ Dim value As String '= ""
+ For i As Integer = 0 To minLen - 1
+ ' Wrap strings in quotes.
+ value = If(GetCsvFieldType(fields(i)) = "String", $"""{fields(i).Trim().Trim(New Char() {""""c})}""", fields(i))
+ sb.AppendLine($" c.{names(i)} = {value}")
+ Next
- sb.AppendLine(" l.Add(c)")
+ sb.AppendLine(" l.Add(c)")
- fields = parser.ReadFields()
+ fields = parser.ReadFields()
- Loop While fields IsNot Nothing
+ Loop While fields IsNot Nothing
- sb.Append($" m_all = l
+ sb.Append($" m_all = l
Return l
")
- ' Close things (property, class, namespace)
- sb.Append(" End Get
+ ' Close things (property, class, namespace)
+ sb.Append(" End Get
End Property
End Class
End Namespace")
- Return sb.ToString()
-
- End Function
-
- Private Shared Function StringToValidPropertyName(s As String) As String
- s = s.Trim()
- s = If(Char.IsLetter(s(0)), Char.ToUpper(s(0)) & s.Substring(1), s)
- s = If(Char.IsDigit(s.Trim()(0)), "_" & s, s)
- s = New String(s.[Select](Function(ch) If(Char.IsDigit(ch) OrElse Char.IsLetter(ch), ch, "_"c)).ToArray())
- Return s
- End Function
-
- Private Shared Function SourceFilesFromAdditionalFile(loadType As CsvLoadType, cacheObjects As Boolean, file As AdditionalText) As IEnumerable(Of (Name As String, Code As String))
- Dim className = Path.GetFileNameWithoutExtension(file.Path)
- Dim csvText = file.GetText().ToString()
- Return New(String, String)() {(className, GenerateClassFile(className, csvText, loadType, cacheObjects))}
- End Function
-
- Private Shared Function SourceFilesFromAdditionalFiles(pathsData As IEnumerable(Of (LoadType As CsvLoadType, CacheObjects As Boolean, File As AdditionalText))) As IEnumerable(Of (Name As String, Code As String))
- Return pathsData.SelectMany(Function(d) SourceFilesFromAdditionalFile(d.LoadType, d.CacheObjects, d.File))
- End Function
-
- Private Shared Iterator Function GetLoadOptions(context As GeneratorExecutionContext) As IEnumerable(Of (LoadType As CsvLoadType, CacheObjects As Boolean, File As AdditionalText))
- For Each file In context.AdditionalFiles
- If Path.GetExtension(file.Path).Equals(".csv", StringComparison.OrdinalIgnoreCase) Then
- ' are there any options for it?
- Dim loadTimeString As String = Nothing
- context.AnalyzerConfigOptions.GetOptions(file).TryGetValue("build_metadata.additionalfiles.CsvLoadType", loadTimeString)
- Dim loadType As CsvLoadType = Nothing
- [Enum].TryParse(loadTimeString, ignoreCase:=True, loadType)
- Dim cacheObjectsString As String = Nothing
- context.AnalyzerConfigOptions.GetOptions(file).TryGetValue("build_metadata.additionalfiles.CacheObjects", cacheObjectsString)
- Dim cacheObjects As Boolean = Nothing
- Boolean.TryParse(cacheObjectsString, cacheObjects)
- Yield (loadType, cacheObjects, file)
- End If
- Next
- End Function
-
- End Class
-
-End Namespace
\ No newline at end of file
+ Return sb.ToString()
+
+ End Function
+
+ Private Shared Function StringToValidPropertyName(s As String) As String
+ s = s.Trim()
+ s = If(Char.IsLetter(s(0)), Char.ToUpper(s(0)) & s.Substring(1), s)
+ s = If(Char.IsDigit(s.Trim()(0)), "_" & s, s)
+ s = New String(s.[Select](Function(ch) If(Char.IsDigit(ch) OrElse Char.IsLetter(ch), ch, "_"c)).ToArray())
+ Return s
+ End Function
+
+ Private Shared Function SourceFilesFromAdditionalFile(loadType As CsvLoadType, cacheObjects As Boolean, file As AdditionalText) As IEnumerable(Of (Name As String, Code As String))
+ Dim className = Path.GetFileNameWithoutExtension(file.Path)
+ Dim csvText = file.GetText().ToString()
+ Return New(String, String)() {(className, GenerateClassFile(className, csvText, loadType, cacheObjects))}
+ End Function
+
+ Private Shared Function SourceFilesFromAdditionalFiles(pathsData As IEnumerable(Of (LoadType As CsvLoadType, CacheObjects As Boolean, File As AdditionalText))) As IEnumerable(Of (Name As String, Code As String))
+ Return pathsData.SelectMany(Function(d) SourceFilesFromAdditionalFile(d.LoadType, d.CacheObjects, d.File))
+ End Function
+
+ Private Shared Iterator Function GetLoadOptions(context As GeneratorExecutionContext) As IEnumerable(Of (LoadType As CsvLoadType, CacheObjects As Boolean, File As AdditionalText))
+ For Each file In context.AdditionalFiles
+ If Path.GetExtension(file.Path).Equals(".csv", StringComparison.OrdinalIgnoreCase) Then
+ ' are there any options for it?
+ Dim loadTimeString As String = Nothing
+ context.AnalyzerConfigOptions.GetOptions(file).TryGetValue("build_metadata.additionalfiles.CsvLoadType", loadTimeString)
+ Dim loadType As CsvLoadType = Nothing
+ [Enum].TryParse(loadTimeString, ignoreCase:=True, loadType)
+ Dim cacheObjectsString As String = Nothing
+ context.AnalyzerConfigOptions.GetOptions(file).TryGetValue("build_metadata.additionalfiles.CacheObjects", cacheObjectsString)
+ Dim cacheObjects As Boolean = Nothing
+ Boolean.TryParse(cacheObjectsString, cacheObjects)
+ Yield (loadType, cacheObjects, file)
+ End If
+ Next
+ End Function
+
+ End Class
+
+End Namespace
diff --git a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/HelloWorldGenerator.vb b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/HelloWorldGenerator.vb
index 792c3b62a..ff4c51ba2 100644
--- a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/HelloWorldGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/HelloWorldGenerator.vb
@@ -9,19 +9,19 @@ Imports Microsoft.CodeAnalysis.Text
Namespace SourceGeneratorSamples
-
- Public Class HelloWorldGenerator
- Implements ISourceGenerator
+
+ Public Class HelloWorldGenerator
+ Implements ISourceGenerator
- Public Sub Initialize(context As GeneratorInitializationContext) Implements ISourceGenerator.Initialize
- ' No initialization required
- End Sub
+ Public Sub Initialize(context As GeneratorInitializationContext) Implements ISourceGenerator.Initialize
+ ' No initialization required
+ End Sub
- Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
+ Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
- ' begin creating the source we'll inject into the users compilation
+ ' begin creating the source we'll inject into the users compilation
- Dim sourceBuilder = New StringBuilder("Option Explicit On
+ Dim sourceBuilder = New StringBuilder("Option Explicit On
Option Strict On
Option Infer On
@@ -35,19 +35,19 @@ Namespace Global.HelloWorldGenerated
Console.WriteLine(""The following syntax trees existed in the compilation that created this program:"")
")
- ' for testing... let's include a comment with the current date/time.
- sourceBuilder.AppendLine($" ' Generated at {DateTime.Now}")
+ ' for testing... let's include a comment with the current date/time.
+ sourceBuilder.AppendLine($" ' Generated at {DateTime.Now}")
- ' using the context, get a list of syntax trees in the users compilation
- ' add the filepath of each tree to the class we're building
+ ' using the context, get a list of syntax trees in the users compilation
+ ' add the filepath of each tree to the class we're building
- For Each tree In context.Compilation.SyntaxTrees
- sourceBuilder.AppendLine($" Console.WriteLine("" - {tree.FilePath}"")")
- Next
+ For Each tree In context.Compilation.SyntaxTrees
+ sourceBuilder.AppendLine($" Console.WriteLine("" - {tree.FilePath}"")")
+ Next
- ' finish creating the source to inject
+ ' finish creating the source to inject
- sourceBuilder.Append("
+ sourceBuilder.Append("
End Sub
@@ -55,12 +55,12 @@ Namespace Global.HelloWorldGenerated
End Namespace")
- ' inject the created source into the users compilation
+ ' inject the created source into the users compilation
- context.AddSource("HelloWorldGenerated", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8))
+ context.AddSource("HelloWorldGenerated", SourceText.From(sourceBuilder.ToString(), Encoding.UTF8))
- End Sub
+ End Sub
- End Class
+ End Class
-End Namespace
\ No newline at end of file
+End Namespace
diff --git a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/MustacheGenerator.vb b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/MustacheGenerator.vb
deleted file mode 100644
index 38004dbe7..000000000
--- a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/MustacheGenerator.vb
+++ /dev/null
@@ -1,146 +0,0 @@
-Option Explicit On
-Option Infer On
-Option Strict On
-
-Imports System.Collections.Immutable
-Imports System.Text
-
-Imports Microsoft.CodeAnalysis
-Imports Microsoft.CodeAnalysis.Text
-
-Imports Microsoft.CodeAnalysis.VisualBasic
-Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
-
-Namespace SourceGeneratorSamples
-
-
- Public Class MustacheGenerator
- Implements ISourceGenerator
-
- Public Sub Initialize(context As GeneratorInitializationContext) Implements ISourceGenerator.Initialize
- ' No initialization required
- End Sub
-
- Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
-
- Dim attributeSource = "Option Explicit On
-Option Strict On
-Option Infer On
-
-Namespace Global
-
-
- Friend NotInheritable Class MustacheAttribute
- Inherits System.Attribute
-
- Public ReadOnly Property Name As String
- Public ReadOnly Property Template As String
- Public ReadOnly Property Hash As String
-
- Public Sub New(name As String, template As String, hash As String)
- Me.Name = name
- Me.Template = template
- Me.Hash = hash
- End Sub
-
- End Class
-
-End Namespace
-"
-
- context.AddSource("Mustache_MainAttributes__", SourceText.From(attributeSource, Encoding.UTF8))
-
- Dim compilation = context.Compilation
-
- Dim options = GetMustacheOptions(compilation)
- Dim namesSources = SourceFilesFromMustachePaths(options)
-
- For Each entry In namesSources
- context.AddSource($"Mustache{entry.Item1}", SourceText.From(entry.Item2, Encoding.UTF8))
- Next
-
- End Sub
-
- Private Shared Iterator Function GetMustacheOptions(compilation As Compilation) As IEnumerable(Of (String, String, String))
-
- ' Get all Mustache attributes
-
- Dim allNodes = compilation.SyntaxTrees.SelectMany(Function(s) s.GetRoot().DescendantNodes())
-
-
- Dim allAttributes = allNodes.Where(Function(d) d.IsKind(SyntaxKind.Attribute)).OfType(Of AttributeSyntax)()
- Dim attributes = allAttributes.Where(Function(d) d.Name.ToString() = "Mustache").ToImmutableArray()
-
- Dim models = compilation.SyntaxTrees.[Select](Function(st) compilation.GetSemanticModel(st))
- For Each att In attributes
-
- Dim mustacheName = ""
- Dim template = ""
- Dim hash = ""
- Dim index = 0
-
- If att.ArgumentList Is Nothing Then
- Throw New Exception("Can't be null here")
- End If
-
- Dim m = compilation.GetSemanticModel(att.SyntaxTree)
-
- For Each arg In att.ArgumentList.Arguments
-
- Dim expr As ExpressionSyntax = Nothing
- If TypeOf arg Is SimpleArgumentSyntax Then
- expr = TryCast(arg, SimpleArgumentSyntax).Expression
- End If
- If expr Is Nothing Then
- Continue For
- End If
-
- Dim t = m.GetTypeInfo(expr)
- Dim v = m.GetConstantValue(expr)
- If index = 0 Then
- mustacheName = v.ToString()
- ElseIf index = 1 Then
- template = v.ToString()
- Else
- hash = v.ToString()
- End If
- index += 1
-
- Next
-
- Yield (mustacheName, template, hash)
-
- Next
-
- End Function
-
- Private Shared Function SourceFileFromMustachePath(name As String, template As String, hash As String) As String
- Dim tree = HandlebarsDotNet.Handlebars.Compile(template)
- Dim o = Newtonsoft.Json.JsonConvert.DeserializeObject(hash)
- Dim mustacheText = tree(o)
- Return GenerateMustacheClass(name, mustacheText)
- End Function
-
- Private Shared Iterator Function SourceFilesFromMustachePaths(pathsData As IEnumerable(Of (Name As String, Template As String, Hash As String))) As IEnumerable(Of (Name As String, Code As String))
- For Each entry In pathsData
- Yield (entry.Name, SourceFileFromMustachePath(entry.Name, entry.Template, entry.Hash))
- Next
- End Function
-
- Private Shared Function GenerateMustacheClass(className As String, mustacheText As String) As String
- Return $"
-
-Namespace Global.Mustache
-
- Partial Public Module Constants
-
- Public Const {className} As String = ""{mustacheText.Replace("""", """""")}""
-
- End Module
-
-End Namespace"
- End Function
-
- End Class
-
-End Namespace
\ No newline at end of file
diff --git a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/SettingsXmlGenerator.vb b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/SettingsXmlGenerator.vb
index 1754315d8..d1ecd628f 100644
--- a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/SettingsXmlGenerator.vb
+++ b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/SettingsXmlGenerator.vb
@@ -11,38 +11,38 @@ Imports Microsoft.CodeAnalysis.Text
Namespace SourceGeneratorSamples
-
- Public Class SettingsXmlGenerator
- Implements ISourceGenerator
-
- Public Sub Initialize(context As GeneratorInitializationContext) Implements ISourceGenerator.Initialize
-
- End Sub
-
- Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
- ' Using the context, get any additional files that end in .xmlsettings
- For Each settingsFile In context.AdditionalFiles.Where(Function(at) at.Path.EndsWith(".xmlsettings"))
- ProcessSettingsFile(settingsFile, context)
- Next
- End Sub
-
- Private Sub ProcessSettingsFile(xmlFile As AdditionalText, context As GeneratorExecutionContext)
-
- ' try and load the settings file
- Dim xmlDoc As New XmlDocument
- Dim text = xmlFile.GetText(context.CancellationToken).ToString()
- Try
- xmlDoc.LoadXml(text)
- Catch
- 'TODO: issue a diagnostic that says we couldn't parse it
- Return
- End Try
-
- ' create a class in the XmlSetting class that represnts this entry, and a static field that contains a singleton instance.
- Dim fileName = Path.GetFileName(xmlFile.Path)
- Dim name = xmlDoc.DocumentElement.GetAttribute("name")
-
- Dim sb = New StringBuilder($"Option Explicit On
+
+ Public Class SettingsXmlGenerator
+ Implements ISourceGenerator
+
+ Public Sub Initialize(context As GeneratorInitializationContext) Implements ISourceGenerator.Initialize
+
+ End Sub
+
+ Public Sub Execute(context As GeneratorExecutionContext) Implements ISourceGenerator.Execute
+ ' Using the context, get any additional files that end in .xmlsettings
+ For Each settingsFile In context.AdditionalFiles.Where(Function(at) at.Path.EndsWith(".xmlsettings"))
+ ProcessSettingsFile(settingsFile, context)
+ Next
+ End Sub
+
+ Private Sub ProcessSettingsFile(xmlFile As AdditionalText, context As GeneratorExecutionContext)
+
+ ' try and load the settings file
+ Dim xmlDoc As New XmlDocument
+ Dim text = xmlFile.GetText(context.CancellationToken).ToString()
+ Try
+ xmlDoc.LoadXml(text)
+ Catch
+ 'TODO: issue a diagnostic that says we couldn't parse it
+ Return
+ End Try
+
+ ' create a class in the XmlSetting class that represnts this entry, and a static field that contains a singleton instance.
+ Dim fileName = Path.GetFileName(xmlFile.Path)
+ Dim name = xmlDoc.DocumentElement.GetAttribute("name")
+
+ Dim sb = New StringBuilder($"Option Explicit On
Option Strict On
Option Infer On
@@ -69,13 +69,13 @@ Namespace Global.AutoSettings
Return m_fileName
End Function")
- For i = 0 To xmlDoc.DocumentElement.ChildNodes.Count - 1
+ For i = 0 To xmlDoc.DocumentElement.ChildNodes.Count - 1
- Dim setting = CType(xmlDoc.DocumentElement.ChildNodes(i), XmlElement)
- Dim settingName = setting.GetAttribute("name")
- Dim settingType = setting.GetAttribute("type")
+ Dim setting = CType(xmlDoc.DocumentElement.ChildNodes(i), XmlElement)
+ Dim settingName = setting.GetAttribute("name")
+ Dim settingType = setting.GetAttribute("type")
- sb.Append($"
+ sb.Append($"
Public ReadOnly Property {settingName} As {settingType}
Get
@@ -83,9 +83,9 @@ Namespace Global.AutoSettings
End Get
End Property")
- Next
+ Next
- sb.Append("
+ sb.Append("
End Class
@@ -93,10 +93,10 @@ Namespace Global.AutoSettings
End Namespace")
- context.AddSource($"Settings_{name}", SourceText.From(sb.ToString(), Encoding.UTF8))
+ context.AddSource($"Settings_{name}", SourceText.From(sb.ToString(), Encoding.UTF8))
- End Sub
+ End Sub
- End Class
+ End Class
-End Namespace
\ No newline at end of file
+End Namespace
diff --git a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/SourceGeneratorSamples.vbproj b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/VisualBasicSourceGeneratorSamples.vbproj
similarity index 61%
rename from samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/SourceGeneratorSamples.vbproj
rename to samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/VisualBasicSourceGeneratorSamples.vbproj
index f719a9496..9e9f12565 100644
--- a/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/SourceGeneratorSamples.vbproj
+++ b/samples/VisualBasic/SourceGenerators/SourceGeneratorSamples/VisualBasicSourceGeneratorSamples.vbproj
@@ -5,15 +5,13 @@
-
+
-
-
@@ -23,8 +21,6 @@
-
-