CSharpGen.Utils.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using MicroComGenerator.Ast;
  6. using Microsoft.CodeAnalysis;
  7. using Microsoft.CodeAnalysis.CSharp;
  8. using Microsoft.CodeAnalysis.CSharp.Formatting;
  9. using Microsoft.CodeAnalysis.CSharp.Syntax;
  10. using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
  11. namespace MicroComGenerator
  12. {
  13. public partial class CSharpGen
  14. {
  15. CompilationUnitSyntax Unit()
  16. => CompilationUnit().WithUsings(List(new[]
  17. {
  18. "System", "System.Text", "System.Collections", "System.Collections.Generic", "Avalonia.MicroCom"
  19. }
  20. .Concat(_extraUsings).Select(u => UsingDirective(IdentifierName(u)))));
  21. string Format(CompilationUnitSyntax unit)
  22. {
  23. var cw = new AdhocWorkspace();
  24. return
  25. "#pragma warning disable 108\n" +
  26. Microsoft.CodeAnalysis.Formatting.Formatter.Format(unit.NormalizeWhitespace(), cw, cw.Options
  27. .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInObjectInit, true)
  28. .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInObjectCollectionArrayInitializers,
  29. true)
  30. .WithChangedOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes, true)
  31. .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, true)
  32. ).ToFullString();
  33. }
  34. SyntaxToken Semicolon() => Token(SyntaxKind.SemicolonToken);
  35. static VariableDeclarationSyntax DeclareVar(string type, string name,
  36. ExpressionSyntax? initializer = null)
  37. => VariableDeclaration(ParseTypeName(type),
  38. SingletonSeparatedList(VariableDeclarator(name)
  39. .WithInitializer(initializer == null ? null : EqualsValueClause(initializer))));
  40. FieldDeclarationSyntax DeclareConstant(string type, string name, LiteralExpressionSyntax value)
  41. => FieldDeclaration(
  42. VariableDeclaration(ParseTypeName(type),
  43. SingletonSeparatedList(
  44. VariableDeclarator(name).WithInitializer(EqualsValueClause(value))
  45. ))
  46. ).WithSemicolonToken(Semicolon())
  47. .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.ConstKeyword)));
  48. FieldDeclarationSyntax DeclareField(string type, string name, params SyntaxKind[] modifiers) =>
  49. DeclareField(type, name, null, modifiers);
  50. FieldDeclarationSyntax DeclareField(string type, string name, EqualsValueClauseSyntax initializer,
  51. params SyntaxKind[] modifiers) =>
  52. FieldDeclaration(
  53. VariableDeclaration(ParseTypeName(type),
  54. SingletonSeparatedList(
  55. VariableDeclarator(name).WithInitializer(initializer))))
  56. .WithSemicolonToken(Semicolon())
  57. .WithModifiers(TokenList(modifiers.Select(x => Token(x))));
  58. bool IsPropertyRewriteCandidate(MethodDeclarationSyntax method)
  59. {
  60. return
  61. method.ReturnType.ToFullString() != "void"
  62. && method.Identifier.Text.StartsWith("Get")
  63. && method.ParameterList.Parameters.Count == 0;
  64. }
  65. TypeDeclarationSyntax RewriteMethodsToProperties<T>(T decl) where T : TypeDeclarationSyntax
  66. {
  67. var replace = new Dictionary<MethodDeclarationSyntax, PropertyDeclarationSyntax>();
  68. foreach (var method in decl.Members.OfType<MethodDeclarationSyntax>().ToList())
  69. {
  70. if (IsPropertyRewriteCandidate(method))
  71. {
  72. var getter = AccessorDeclaration(SyntaxKind.GetAccessorDeclaration);
  73. if (method.Body != null)
  74. getter = getter.WithBody(method.Body);
  75. else
  76. getter = getter.WithSemicolonToken(Semicolon());
  77. replace[method] = PropertyDeclaration(method.ReturnType,
  78. method.Identifier.Text.Substring(3))
  79. .WithModifiers(method.Modifiers).AddAccessorListAccessors(getter);
  80. }
  81. }
  82. return decl.ReplaceNodes(replace.Keys, (m, m2) => replace[m]);
  83. }
  84. bool IsInterface(string name)
  85. {
  86. if (name == "IUnknown")
  87. return true;
  88. return _idl.Interfaces.Any(i => i.Name == name);
  89. }
  90. private bool IsInterface(AstTypeNode type) => IsInterface(type.Name);
  91. }
  92. }