Source Generation
This is v1 of the new source generator.
This commit is contained in:
parent
db04b3b356
commit
84af952300
94
.gitignore
vendored
Normal file
94
.gitignore
vendored
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# ---> JetBrains
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
.idea/**/.idea/**
|
||||||
|
.idea/**/.idea/
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
16
ServerDatabase.SourceGenerator.sln
Normal file
16
ServerDatabase.SourceGenerator.sln
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerDatabase.SourceGenerator", "ServerDatabase.SourceGenerator\ServerDatabase.SourceGenerator.csproj", "{2F4102DB-3F1D-463F-AC27-EA56616DA96D}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{2F4102DB-3F1D-463F-AC27-EA56616DA96D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2F4102DB-3F1D-463F-AC27-EA56616DA96D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2F4102DB-3F1D-463F-AC27-EA56616DA96D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2F4102DB-3F1D-463F-AC27-EA56616DA96D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -0,0 +1,31 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<LangVersion>latestmajor</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<IncludeBuildOutput>true</IncludeBuildOutput>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Title>Server Database Source Generator</Title>
|
||||||
|
<Authors>JacobTech</Authors>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="CustomActionsAfterPack" AfterTargets="Pack">
|
||||||
|
<Message Text="Actions AfterPack: $(PackageId).$(PackageVersion).nupkg" Importance="high" />
|
||||||
|
<Exec Command="nuget push -Source https://nuget.jacobtech.com/v3/index.json bin/Release/$(PackageId).$(PackageVersion).nupkg" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
12
ServerDatabase.SourceGenerator/TableRowAttribute.cs
Normal file
12
ServerDatabase.SourceGenerator/TableRowAttribute.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace ServerDatabase.SourceGenerator;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||||
|
public sealed class TableRowAttribute : Attribute
|
||||||
|
{
|
||||||
|
public TableRowAttribute(Type type)
|
||||||
|
{
|
||||||
|
this.Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type Type { get; private set; }
|
||||||
|
}
|
109
ServerDatabase.SourceGenerator/TableRowGenerator.cs
Normal file
109
ServerDatabase.SourceGenerator/TableRowGenerator.cs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
using TypeInfo = Microsoft.CodeAnalysis.TypeInfo;
|
||||||
|
|
||||||
|
namespace ServerDatabase.SourceGenerator;
|
||||||
|
|
||||||
|
[Generator]
|
||||||
|
public class TableRowGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (!Debugger.IsAttached) Debugger.Launch();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
INamedTypeSymbol? attributeSymbol = context.Compilation.GetTypeByMetadataName(typeof(TableRowAttribute).FullName);
|
||||||
|
|
||||||
|
IEnumerable<SyntaxTree> classWithAttributes = context.Compilation.SyntaxTrees.Where(st => st.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>()
|
||||||
|
.Any(p => p.DescendantNodes().OfType<AttributeSyntax>().Any()));
|
||||||
|
|
||||||
|
foreach (SyntaxTree? tree in classWithAttributes)
|
||||||
|
{
|
||||||
|
if (tree is null) continue;
|
||||||
|
SemanticModel semanticModel = context.Compilation.GetSemanticModel(tree);
|
||||||
|
foreach (ClassDeclarationSyntax? declaredClass in tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().Where(cd => cd.DescendantNodes().OfType<AttributeSyntax>().Any()))
|
||||||
|
{
|
||||||
|
if (declaredClass is null) continue;
|
||||||
|
List<SyntaxToken>? nodes = declaredClass
|
||||||
|
.DescendantNodes()
|
||||||
|
.OfType<AttributeSyntax>()
|
||||||
|
.FirstOrDefault(a => a.DescendantTokens().Any(dt => dt.IsKind(SyntaxKind.IdentifierToken) && dt.Parent is not null && semanticModel.GetTypeInfo(dt.Parent).Type is not null && semanticModel.GetTypeInfo(dt.Parent).Type.Name == attributeSymbol.Name))
|
||||||
|
?.DescendantTokens()
|
||||||
|
?.Where(dt => dt.IsKind(SyntaxKind.IdentifierToken))
|
||||||
|
?.ToList();
|
||||||
|
|
||||||
|
if(nodes == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfo relatedClass = semanticModel.GetTypeInfo(nodes.Last().Parent);
|
||||||
|
|
||||||
|
StringBuilder generatedClass = this.GenerateClass(tree.GetRoot().DescendantNodes().OfType<FileScopedNamespaceDeclarationSyntax>().First().Name.ToString(), declaredClass);
|
||||||
|
|
||||||
|
foreach(IPropertySymbol? classProperty in relatedClass.Type.GetMembers().OfType<IPropertySymbol>())
|
||||||
|
{
|
||||||
|
this.GenerateProperty(classProperty, ref generatedClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.CloseClass(generatedClass);
|
||||||
|
|
||||||
|
context.AddSource($"{declaredClass.Identifier}_{relatedClass.Type.Name}.g.cs", SourceText.From(generatedClass.ToString(), Encoding.UTF8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
context.AddSource("teste.g.cs", SourceText.From(@$"using System;
|
||||||
|
namespace ServerDatabase.SourceGenerator.Generated
|
||||||
|
{{
|
||||||
|
public class bobe
|
||||||
|
{{
|
||||||
|
public string e = @""{e}"";
|
||||||
|
}}
|
||||||
|
}}", Encoding.UTF8));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateProperty(IPropertySymbol prop, ref StringBuilder builder)
|
||||||
|
{
|
||||||
|
string bad = prop.Type.ToString();
|
||||||
|
bad = bad.Replace("ServerDatabase.TableColumn<", "");
|
||||||
|
bad = bad.Remove(bad.LastIndexOf('>'));
|
||||||
|
builder.AppendLine($" public {bad} {prop.Name} {{ get; set; }}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder GenerateClass(string n, ClassDeclarationSyntax og)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append(@$"using System;
|
||||||
|
|
||||||
|
namespace {n}
|
||||||
|
{{
|
||||||
|
public partial class " + og.Identifier);
|
||||||
|
|
||||||
|
sb.Append(@"
|
||||||
|
{
|
||||||
|
");
|
||||||
|
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseClass(StringBuilder generatedClass)
|
||||||
|
{
|
||||||
|
generatedClass.Append(
|
||||||
|
@" }
|
||||||
|
}");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user