* Implicit handlers building extensions generator refactored
* Telegram.Bot package updated
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.Collections.Immutable;
|
||||
using System.Text;
|
||||
using Telegrator.RoslynExtensions;
|
||||
using Telegrator.Analyzers.RoslynExtensions;
|
||||
|
||||
namespace Telegrator.Analyzers
|
||||
{
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.Collections.Immutable;
|
||||
using Telegrator.RoslynExtensions;
|
||||
using Telegrator.Analyzers.RoslynExtensions;
|
||||
|
||||
|
||||
#if DEBUG
|
||||
using System.Diagnostics;
|
||||
@@ -69,7 +70,11 @@ namespace Telegrator.Analyzers
|
||||
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
IncrementalValueProvider<ImmutableArray<MethodDeclarationSyntax>> pipeline = context.SyntaxProvider.CreateSyntaxProvider(Provide, Transform).Where(x => x != null).Collect();
|
||||
IncrementalValueProvider<ImmutableArray<MethodDeclarationSyntax>> pipeline = context.SyntaxProvider
|
||||
.CreateSyntaxProvider(Provide, Transform)
|
||||
.Where(x => x != null)
|
||||
.Collect();
|
||||
|
||||
context.RegisterSourceOutput(pipeline, Execute);
|
||||
}
|
||||
|
||||
@@ -183,21 +188,10 @@ namespace Telegrator.Analyzers
|
||||
|
||||
try
|
||||
{
|
||||
if (model.OriginalMethod.Parent is not ClassDeclarationSyntax containerClass)
|
||||
if (model.OriginalMethod.Parent is not ClassDeclarationSyntax)
|
||||
throw new MissingMemberException();
|
||||
|
||||
FieldDeclarationSyntax genField = model.GeneratedField
|
||||
.WithLeadingTrivia(NewLineTrivia, TabulationTrivia, TabulationTrivia);
|
||||
|
||||
MethodDeclarationSyntax genMethod = model.GeneratedMethod
|
||||
.WithLeadingTrivia(NewLineTrivia, TabulationTrivia, TabulationTrivia);
|
||||
|
||||
//ClassDeclarationSyntax genClass = GeneratedClassDeclaration(containerClass.Identifier.WithLeadingTrivia(WhitespaceTrivia).WithTrailingTrivia(NewLineTrivia), containerClass.Modifiers, genField, genMethod);
|
||||
NamespaceDeclarationSyntax genNamespace = GeneratedNamespaceDeclaration(model.OriginalMethod, [genField, genMethod]);
|
||||
|
||||
genNamespace = genNamespace
|
||||
.WithCloseBraceToken(genNamespace.CloseBraceToken.WithLeadingTrivia(NewLineTrivia));
|
||||
|
||||
NamespaceDeclarationSyntax genNamespace = GeneratedNamespaceDeclaration(model.OriginalMethod, [model.GeneratedField, model.GeneratedMethod]);
|
||||
compilationUnit = compilationUnit.AddMembers(genNamespace);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -210,30 +204,6 @@ namespace Telegrator.Analyzers
|
||||
context.AddSource("GeneratedKeyboards.g", compilationUnit.ToFullString());
|
||||
}
|
||||
|
||||
/*
|
||||
private static NamespaceDeclarationSyntax GeneratedNamespaceDeclaration(NameSyntax name, params IEnumerable<MemberDeclarationSyntax> members)
|
||||
{
|
||||
NamespaceDeclarationSyntax genNamespace = SyntaxFactory.NamespaceDeclaration(name)
|
||||
.WithMembers(new SyntaxList<MemberDeclarationSyntax>(members))
|
||||
.WithLeadingTrivia(NewLineTrivia);
|
||||
|
||||
return genNamespace
|
||||
.WithCloseBraceToken(genNamespace.CloseBraceToken.WithLeadingTrivia(NewLineTrivia));
|
||||
}
|
||||
|
||||
private static ClassDeclarationSyntax GeneratedClassDeclaration(SyntaxToken identifier, SyntaxTokenList modifiers, params IEnumerable<MemberDeclarationSyntax> members)
|
||||
{
|
||||
ClassDeclarationSyntax genClass = SyntaxFactory.ClassDeclaration(identifier)
|
||||
.WithMembers(new SyntaxList<MemberDeclarationSyntax>(members))
|
||||
.WithModifiers(modifiers)
|
||||
.WithLeadingTrivia(NewLineTrivia, TabulationTrivia);
|
||||
|
||||
return genClass
|
||||
.WithOpenBraceToken(genClass.OpenBraceToken.WithLeadingTrivia(TabulationTrivia))
|
||||
.WithCloseBraceToken(genClass.CloseBraceToken.WithLeadingTrivia(NewLineTrivia, TabulationTrivia));
|
||||
}
|
||||
*/
|
||||
|
||||
private static MethodDeclarationSyntax GeneratedMethodDeclaration(string identifier, SyntaxTokenList modifiers, TypeSyntax returnType, FieldDeclarationSyntax field)
|
||||
{
|
||||
return SyntaxFactory.MethodDeclaration(returnType.WithTrailingTrivia(WhitespaceTrivia), identifier)
|
||||
@@ -267,11 +237,11 @@ namespace Telegrator.Analyzers
|
||||
if (method.Parent is not ClassDeclarationSyntax containerClass)
|
||||
throw new MemberAccessException();
|
||||
|
||||
int times = method.CountParentTree() - 1;
|
||||
int times = method.CountParentTree();
|
||||
ClassDeclarationSyntax generatedContainerClass = SyntaxFactory.ClassDeclaration(containerClass.Identifier)
|
||||
.WithMembers(new SyntaxList<MemberDeclarationSyntax>(generatedMembers.Select(member => member.DecorateMember(times + 1))))
|
||||
.WithModifiers(containerClass.Modifiers.Decorate())
|
||||
.Decorate(times);
|
||||
.DecorateType(times);
|
||||
|
||||
MemberDeclarationSyntax generated = generatedContainerClass;
|
||||
MemberDeclarationSyntax inspecting = containerClass;
|
||||
@@ -290,7 +260,7 @@ namespace Telegrator.Analyzers
|
||||
generated = SyntaxFactory.ClassDeclaration(classDeclaration.Identifier)
|
||||
.WithMembers([generated])
|
||||
.WithModifiers(classDeclaration.Modifiers.Decorate())
|
||||
.Decorate(times);
|
||||
.DecorateType(times);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -300,7 +270,7 @@ namespace Telegrator.Analyzers
|
||||
generated = SyntaxFactory.StructDeclaration(structDeclaration.Identifier)
|
||||
.WithMembers([generated])
|
||||
.WithModifiers(structDeclaration.Modifiers.Decorate())
|
||||
.Decorate(times);
|
||||
.DecorateType(times);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
namespace Telegrator.Analyzers.RoslynExtensions
|
||||
{
|
||||
public static class CollectionsExtensions
|
||||
{
|
||||
public static IEnumerable<TSource> Combine<TSource>(params IEnumerable<TSource>[] collections)
|
||||
=> collections.SelectMany(x => x);
|
||||
|
||||
public static IEnumerable<TSource> IntersectBy<TSource, TValue>(this IEnumerable<TSource> first, IEnumerable<TValue> second, Func<TSource, TValue> selector)
|
||||
{
|
||||
foreach (TSource item in first)
|
||||
{
|
||||
TValue value = selector(item);
|
||||
if (second.Contains(value))
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
public static IList<TValue> UnionAdd<TValue>(this IList<TValue> source, IEnumerable<TValue> toUnion)
|
||||
{
|
||||
foreach (TValue toUnionValue in toUnion)
|
||||
{
|
||||
if (!source.Contains(toUnionValue, EqualityComparer<TValue>.Default))
|
||||
source.Add(toUnionValue);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
public static void UnionAdd<TSource>(this ICollection<TSource> collection, IEnumerable<TSource> target)
|
||||
{
|
||||
foreach (TSource item in target)
|
||||
{
|
||||
if (!collection.Contains(item))
|
||||
collection.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnionAdd<TSource>(this SortedList<TSource, TSource> collection, IEnumerable<TSource> target)
|
||||
{
|
||||
foreach (TSource item in target)
|
||||
{
|
||||
if (!collection.Values.Contains(item))
|
||||
collection.Add(item, item);
|
||||
}
|
||||
}
|
||||
|
||||
public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (T item in source)
|
||||
{
|
||||
if (predicate.Invoke(item))
|
||||
return index;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Repeat<T>(this T item, int times)
|
||||
=> Enumerable.Range(0, times).Select(_ => item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Telegrator.Analyzers.RoslynExtensions
|
||||
{
|
||||
public static class DiagnosticsHelper
|
||||
{
|
||||
public static Diagnostic Create(this DiagnosticDescriptor descriptor, Location? location, params object[] messageArgs)
|
||||
=> Diagnostic.Create(descriptor, location, messageArgs);
|
||||
|
||||
public static void Report(this Diagnostic diagnostic, SourceProductionContext context)
|
||||
=> context.ReportDiagnostic(diagnostic);
|
||||
|
||||
public static void Report(this DiagnosticDescriptor descriptor, SourceProductionContext context, Location? location, params object[] messageArgs)
|
||||
=> descriptor.Create(location, messageArgs).Report(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Telegrator.Analyzers.RoslynExtensions;
|
||||
|
||||
public class TargteterNotFoundException() : Exception() { }
|
||||
|
||||
public class BaseClassTypeNotFoundException() : Exception() { }
|
||||
|
||||
public class AncestorNotFoundException : Exception { }
|
||||
@@ -0,0 +1,38 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
|
||||
namespace Telegrator.Analyzers.RoslynExtensions
|
||||
{
|
||||
public static class MemberDeclarationSyntaxExtensions
|
||||
{
|
||||
private static SyntaxTrivia TabulationTrivia => SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, "\t");
|
||||
private static SyntaxTrivia WhitespaceTrivia => SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " ");
|
||||
private static SyntaxTrivia NewLineTrivia => SyntaxFactory.SyntaxTrivia(SyntaxKind.EndOfLineTrivia, "\n");
|
||||
|
||||
public static SyntaxTokenList Decorate(this SyntaxTokenList tokens)
|
||||
=> new SyntaxTokenList(tokens.Select(token => token.WithoutTrivia().WithTrailingTrivia(WhitespaceTrivia)).ToArray());
|
||||
|
||||
public static BlockSyntax DecorateBlock(this BlockSyntax block, int times) => block
|
||||
.WithStatements([.. block.Statements.Select(statement => statement.DecorateStatememnt(times + 1))])
|
||||
.WithOpenBraceToken(SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithLeadingTrivia(TabulationTrivia.Repeat(times)).WithTrailingTrivia(NewLineTrivia))
|
||||
.WithCloseBraceToken(SyntaxFactory.Token(SyntaxKind.CloseBraceToken).WithLeadingTrivia(TabulationTrivia.Repeat(times)).WithTrailingTrivia(NewLineTrivia));
|
||||
|
||||
public static T DecorateStatememnt<T>(this T statememnt, int times) where T : StatementSyntax => statememnt
|
||||
.WithoutTrivia().WithLeadingTrivia(TabulationTrivia.Repeat(times)).WithTrailingTrivia(NewLineTrivia);
|
||||
|
||||
public static T DecorateMember<T>(this T typeDeclaration, int times) where T : MemberDeclarationSyntax => typeDeclaration
|
||||
.WithoutTrivia().WithLeadingTrivia(TabulationTrivia.Repeat(times)).WithTrailingTrivia(NewLineTrivia);
|
||||
|
||||
public static NamespaceDeclarationSyntax Decorate(this NamespaceDeclarationSyntax namespaceDeclaration) => namespaceDeclaration
|
||||
.WithName(namespaceDeclaration.Name.WithoutTrivia().WithLeadingTrivia(WhitespaceTrivia))
|
||||
.WithOpenBraceToken(SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithLeadingTrivia(NewLineTrivia).WithTrailingTrivia(NewLineTrivia))
|
||||
.WithCloseBraceToken(SyntaxFactory.Token(SyntaxKind.CloseBraceToken));
|
||||
|
||||
public static T DecorateType<T>(this T typeDeclaration, int times = 1) where T : TypeDeclarationSyntax => (T)typeDeclaration
|
||||
.WithoutTrivia().WithLeadingTrivia(TabulationTrivia.Repeat(times))
|
||||
.WithIdentifier(typeDeclaration.Identifier.WithoutTrivia().WithLeadingTrivia(WhitespaceTrivia).WithTrailingTrivia(NewLineTrivia))
|
||||
.WithOpenBraceToken(SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithLeadingTrivia(TabulationTrivia.Repeat(times)).WithTrailingTrivia(NewLineTrivia))
|
||||
.WithCloseBraceToken(SyntaxFactory.Token(SyntaxKind.CloseBraceToken).WithLeadingTrivia(TabulationTrivia.Repeat(times)).WithTrailingTrivia(NewLineTrivia));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Telegrator.Analyzers.RoslynExtensions
|
||||
{
|
||||
public static class StringBuilderExtensions
|
||||
{
|
||||
public static StringBuilder AppendTabs(this StringBuilder builder, int count)
|
||||
=> builder.Append(new string('\t', count));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Telegrator.Analyzers.RoslynExtensions
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static string FirstLetterToUpper(this string target)
|
||||
{
|
||||
char[] chars = target.ToCharArray();
|
||||
int index = chars.IndexOf(char.IsLetter);
|
||||
chars[index] = char.ToUpper(chars[index]);
|
||||
return new string(chars);
|
||||
}
|
||||
|
||||
public static string FirstLetterToLower(this string target)
|
||||
{
|
||||
char[] chars = target.ToCharArray();
|
||||
int index = chars.IndexOf(char.IsLetter);
|
||||
chars[index] = char.ToLower(chars[index]);
|
||||
return new string(chars);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Telegrator.Analyzers.RoslynExtensions;
|
||||
|
||||
public static class SymbolsExtensions
|
||||
{
|
||||
public static bool IsAssignableFrom(this ITypeSymbol symbol, string className)
|
||||
{
|
||||
if (symbol.BaseType == null)
|
||||
return false;
|
||||
|
||||
if (symbol.BaseType.Name == className)
|
||||
return true;
|
||||
|
||||
return symbol.BaseType.IsAssignableFrom(className);
|
||||
}
|
||||
|
||||
public static ITypeSymbol? Cast(this ITypeSymbol symbol, string className)
|
||||
{
|
||||
if (symbol.BaseType == null)
|
||||
return null;
|
||||
|
||||
if (symbol.BaseType.Name == className)
|
||||
return symbol.BaseType;
|
||||
|
||||
return symbol.BaseType.Cast(className);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
|
||||
namespace Telegrator.Analyzers.RoslynExtensions
|
||||
{
|
||||
public static class SyntaxNodesExtensions
|
||||
{
|
||||
public static T FindAncestor<T>(this SyntaxNode node) where T : SyntaxNode
|
||||
{
|
||||
if (node.Parent == null)
|
||||
throw new AncestorNotFoundException();
|
||||
|
||||
if (node.Parent is T found)
|
||||
return found;
|
||||
|
||||
return node.Parent.FindAncestor<T>();
|
||||
}
|
||||
|
||||
public static bool TryFindAncestor<T>(this SyntaxNode node, out T syntax) where T : SyntaxNode
|
||||
{
|
||||
if (node.Parent == null)
|
||||
{
|
||||
syntax = null!;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node.Parent is T found)
|
||||
{
|
||||
syntax = found;
|
||||
return true;
|
||||
}
|
||||
|
||||
return node.Parent.TryFindAncestor(out syntax);
|
||||
}
|
||||
|
||||
public static INamedTypeSymbol TryGetNamedType(this BaseTypeDeclarationSyntax syntax, Compilation compilation)
|
||||
{
|
||||
SemanticModel semanticModel = compilation.GetSemanticModel(syntax.SyntaxTree);
|
||||
return semanticModel.GetDeclaredSymbol(syntax)!;
|
||||
}
|
||||
|
||||
public static string GetBaseTypeSyntaxName(this BaseTypeSyntax baseClassSyntax)
|
||||
{
|
||||
if (baseClassSyntax is PrimaryConstructorBaseTypeSyntax parimaryConstructor)
|
||||
return parimaryConstructor.Type.ToString();
|
||||
|
||||
if (baseClassSyntax is SimpleBaseTypeSyntax simpleBaseType)
|
||||
return simpleBaseType.Type.ToString();
|
||||
|
||||
throw new BaseClassTypeNotFoundException();
|
||||
}
|
||||
|
||||
public static int CountParentTree(this SyntaxNode node)
|
||||
{
|
||||
int count = 0;
|
||||
SyntaxNode inspectNode = node;
|
||||
|
||||
while (inspectNode.Parent != null)
|
||||
{
|
||||
inspectNode = inspectNode.Parent;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static SeparatedSyntaxList<TNode> ToSeparatedSyntaxList<TNode>(this IEnumerable<TNode> elements) where TNode : SyntaxNode
|
||||
=> new SeparatedSyntaxList<TNode>().AddRange(elements);
|
||||
|
||||
public static SyntaxList<TNode> ToSyntaxList<TNode>(this IEnumerable<TNode> elements) where TNode : SyntaxNode
|
||||
=> new SyntaxList<TNode>().AddRange(elements);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Telegrator.Analyzers.RoslynExtensions
|
||||
{
|
||||
public static class SyntaxTokenExtensions
|
||||
{
|
||||
public static bool HasModifiers(this SyntaxTokenList modifiers, params string[] expected)
|
||||
{
|
||||
return modifiers.Count(mod => expected.Contains(mod.ToString())) == expected.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -22,10 +21,5 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\dev\Telegrator.RoslynExtensions\Telegrator.RoslynExtensions.csproj" PrivateAssets="all" />
|
||||
<None Include="$(OutputPath)\*.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user