示例#1
0
        public void Execute(GeneratorExecutionContext context)
        {
            if (context.SyntaxReceiver is not InjectSyntaxReceiver receiver)
            {
                return;
            }

            foreach (var @class in receiver.GetSymbols(context))
            {
                MemberDeclarationSyntax?type = @class.Rewrite();
                if (type is null)
                {
                    continue;
                }

                var @namespace = @class.ContainingNamespace?.Rewrite()
                                 ?.WithMembers(List(new[] { type }));

                var sourceText = CompilationUnit()
                                 .WithUsings(List(@class.GetUsingDirectives()))
                                 .WithMembers(List(new[] { @namespace ?? type }))
                                 .WithLeadingTrivia(TriviaList(Trivia(PragmaWarningDirectiveTrivia(Token(DisableKeyword), true))))
                                 .NormalizeWhitespace()
                                 .ToFullString();

                context.AddSource($"Lightning_{@class.MetadataName}.cs", sourceText);
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            ImmutableArray <String> exceptions = ImmutableArray <String> .Empty;

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                if (diagnostic.Properties.TryGetValue(AnalysisContextExtensions.ExceptionMetadataName, out String exception))
                {
                    exceptions = exceptions.Add(exception);
                }
            }

            SyntaxNode?root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            MemberDeclarationSyntax?declaration = root?
                                                  .FindToken(context.Diagnostics.First().Location.SourceSpan.Start)
                                                  .Parent.AncestorsAndSelf()
                                                  .OfType <MemberDeclarationSyntax>()
                                                  .FirstOrDefault();

            if (!exceptions.IsDefaultOrEmpty && !(declaration is null))
            {
                CodeAction action = CodeAction.Create(
                    title: "Add exception documentation",
                    createChangedDocument: cancellationToken => DocumentExceptionsAsync(context.Document, declaration, exceptions),
                    equivalenceKey: "DocumentExceptions"
                    );

                context.RegisterCodeFix(action, context.Diagnostics);
            }
        }
        public Task <SyntaxList <MemberDeclarationSyntax> > GenerateAsync(TransformationContext context, IProgress <Diagnostic> progress, CancellationToken cancellationToken)
        {
            var results = SyntaxFactory.List <MemberDeclarationSyntax>();

            MemberDeclarationSyntax?copy = null;
            var applyToClass             = context.ProcessingNode as ClassDeclarationSyntax;

            if (applyToClass != null)
            {
                var properties = applyToClass.Members.OfType <PropertyDeclarationSyntax>()
                                 .Select(x =>
                {
                    var propertySymbol = context.SemanticModel.GetDeclaredSymbol(x);
                    var attribute      = propertySymbol?.GetAttributes()
                                         .FirstOrDefault(a => a.AttributeClass.Name == nameof(TestAttribute));
                    string suffix = "Suff" + string.Concat(attribute?.NamedArguments.Select(a => a.Value.Value !.ToString()) ?? Enumerable.Empty <string>());
                    return((MemberDeclarationSyntax)MethodDeclaration(ParseTypeName("void"), x.Identifier.ValueText + suffix)
                           .AddModifiers(Token(SyntaxKind.PublicKeyword))
                           .AddBodyStatements(Block()));
                });
                copy = ClassDeclaration(applyToClass.Identifier).WithModifiers(applyToClass.Modifiers).AddMembers(properties.ToArray());
            }

            if (copy != null)
            {
                results = results.Add(copy);
            }

            return(Task.FromResult(results));
        }
示例#4
0
        private static IReadOnlyCollection <MemberDeclarationSyntax> Generate(NamespaceWrapper root, ISet <string> excludeMembersAttributes, ISet <string> excludeAttributes, Nullability currentNullability, Func <TypeWrapper, bool> excludeFunc)
        {
            var namespaces = GetAllNamespaces(root)
                             .AsParallel()
                             .Select(namespaceInfo =>
                                     (namespaceInfo, members: namespaceInfo
                                      .Members
                                      .OrderByAndExclude(excludeMembersAttributes, excludeAttributes)
                                      .Where(x => !x.IsNested)
                                      .ToList()))
                             .Where(x => x.members.Count > 0)
                             .OrderBy(x => x.namespaceInfo.FullName)
                             .ToList();

            var output = new List <MemberDeclarationSyntax> [namespaces.Count];

            Parallel.For(
                0,
                namespaces.Count,
                namespaceIndex =>
            {
                var(namespaceInfo, types) = namespaces[namespaceIndex];

                if (types.Count == 0)
                {
                    return;
                }

                var list = new List <MemberDeclarationSyntax>(types.Count);
                output[namespaceIndex] = list;

                var members = new MemberDeclarationSyntax?[types.Count];

                Parallel.For(
                    0,
                    types.Count,
                    i =>
                {
                    var current = types[i];
                    var member  = Generate(current, excludeMembersAttributes, excludeAttributes, excludeFunc, currentNullability, 1);

                    if (member != null)
                    {
                        members[i] = member.AddTrialingNewLines().AddLeadingNewLines(i == 0 ? 1 : 0);
                    }
                });

                var namespaceName = namespaceInfo.FullName;

                var validMembers = members.Where(x => x != null).Select(x => x !).ToList();
                if (string.IsNullOrEmpty(namespaceName))
                {
                    list.AddRange(validMembers);
                }
                else
                {
                    list.Add(NamespaceDeclaration(namespaceName, validMembers, namespaceIndex != 0));
                }
            });
示例#5
0
 public JsonType(TypeName type, Func <ImmutableDictionary <TypeName, JsonType>, string>?directReadExpression, Func <ImmutableDictionary <TypeName, JsonType>, string, string>?directWriteStatement, string?converterName, MemberDeclarationSyntax?constructionMember, MemberDeclarationSyntax?outputMember, TinyType?tinyType)
 {
     Type = type;
     DirectReadExpression = directReadExpression;
     DirectWriteStatement = directWriteStatement;
     ConverterName        = converterName;
     ConstructionMember   = constructionMember;
     TinyType             = tinyType;
     OutputMember         = outputMember;
 }
    private static Task <Document> ChangeAccessibilityAsync(
        Document document,
        SyntaxNode root,
        MemberDeclarationSyntax?declaration,
        SyntaxKind accessibility)
    {
        if (declaration is null)
        {
            return(Task.FromResult(document));
        }

        var firstModifier         = declaration.Modifiers.FirstOrDefault();
        var newModifiers          = declaration.Modifiers;
        var isFirstModiferRemoved = false;

        foreach (var currentModifier in newModifiers)
        {
            if (currentModifier.Kind() is SyntaxKind.PrivateKeyword or SyntaxKind.ProtectedKeyword or SyntaxKind.InternalKeyword or SyntaxKind.PublicKeyword && !currentModifier.IsKind(accessibility))
            {
                newModifiers = newModifiers.Remove(currentModifier);

                if (currentModifier == firstModifier)
                {
                    isFirstModiferRemoved = true;
                }
            }
        }

        if (!isFirstModiferRemoved && firstModifier.HasLeadingTrivia)
        {
            newModifiers = newModifiers.RemoveAt(0).Insert(0, firstModifier.WithLeadingTrivia(SyntaxTriviaList.Empty));
        }

        var publicSyntax = SyntaxFactory.Token(accessibility);

        if (firstModifier.HasLeadingTrivia)
        {
            publicSyntax = publicSyntax.WithLeadingTrivia(declaration.Modifiers.FirstOrDefault().LeadingTrivia);
        }

        if (firstModifier.HasTrailingTrivia)
        {
            publicSyntax = publicSyntax.WithTrailingTrivia(declaration.Modifiers.FirstOrDefault().TrailingTrivia);
        }

        newModifiers = newModifiers.Insert(0, publicSyntax);

        var newDeclaration = declaration.WithModifiers(newModifiers);
        var newRoot        = root.ReplaceNode(declaration, newDeclaration);
        var newDoc         = document.WithSyntaxRoot(newRoot);

        return(Task.FromResult(newDoc));
    }
        private bool IsPublic(MemberDeclarationSyntax?methodDecl)
        {
            if (methodDecl is null || methodDecl is NamespaceDeclarationSyntax)
            {
                return(true);
            }

            if (!methodDecl.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword)))
            {
                return(false);
            }

            return(IsPublic(methodDecl.Parent as MemberDeclarationSyntax));
        }
        /// <summary>Compares two nodes and returns a value indicating whether one is less than, equal to, or greater than the other according to StyleCop.</summary>
        /// <returns>A signed integer that indicates if the node should be before the other according to StyleCop.</returns>
        /// <param name="x">The first node to compare.</param>
        /// <param name="y">The second node to compare.</param>
        public static int Compare(MemberDeclarationSyntax?x, MemberDeclarationSyntax?y)
        {
            if (TryCompare <FieldDeclarationSyntax>(x, y, FieldDeclarationComparer.Compare, out var result) ||
                TryCompare <ConstructorDeclarationSyntax>(x, y, ConstructorDeclarationComparer.Compare, out result) ||
                TryCompareEvent(x, y, out result) ||
                TryCompare <EnumDeclarationSyntax>(x, y, EnumDeclarationComparer.Compare, out result) ||
                TryCompare <PropertyDeclarationSyntax>(x, y, PropertyDeclarationComparer.Compare, out result) ||
                TryCompare <IndexerDeclarationSyntax>(x, y, IndexerDeclarationComparer.Compare, out result) ||
                TryCompare <MethodDeclarationSyntax>(x, y, MethodDeclarationComparer.Compare, out result) ||
                TryCompare <StructDeclarationSyntax>(x, y, StructDeclarationComparer.Compare, out result) ||
                TryCompare <ClassDeclarationSyntax>(x, y, ClassDeclarationComparer.Compare, out result))
            {
                return(result);
            }

            return(0);
        }
    private static Task <Document> AddTypeModifierAsync(
        Document document,
        SyntaxNode root,
        MemberDeclarationSyntax?declaration,
        SyntaxKind modifier)
    {
        if (declaration is null)
        {
            return(Task.FromResult(document));
        }

        var newModifier           = SyntaxFactory.Token(modifier);
        var indexOfPartialKeyword = declaration.Modifiers.IndexOf(SyntaxKind.PartialKeyword);
        var newDeclaration        = indexOfPartialKeyword < 0 ? declaration.AddModifiers(newModifier) : declaration.WithModifiers(declaration.Modifiers.Insert(indexOfPartialKeyword, newModifier));
        var newRoot = root.ReplaceNode(declaration, newDeclaration);
        var newDoc  = document.WithSyntaxRoot(newRoot);

        return(Task.FromResult(newDoc));
    }
示例#10
0
        public Task <SyntaxList <MemberDeclarationSyntax> > GenerateAsync(TransformationContext context, IProgress <Diagnostic> progress, CancellationToken cancellationToken)
        {
            var results = SyntaxFactory.List <MemberDeclarationSyntax>();

            MemberDeclarationSyntax?copy = null;
            var applyToClass             = context.ProcessingNode as ClassDeclarationSyntax;

            if (applyToClass != null)
            {
                copy = applyToClass
                       .WithIdentifier(SyntaxFactory.Identifier(applyToClass.Identifier.ValueText + this.suffix));
            }

            if (copy != null)
            {
                results = results.Add(copy);
            }

            return(Task.FromResult(results));
        }
        public Task <SyntaxList <MemberDeclarationSyntax> > GenerateAsync(TransformationContext context, IProgress <Diagnostic> progress, CancellationToken cancellationToken)
        {
            var results = SyntaxFactory.List <MemberDeclarationSyntax>();

            MemberDeclarationSyntax?copy = null;
            var applyToClass             = context.ProcessingNode as MethodDeclarationSyntax;

            if (applyToClass != null)
            {
                copy = applyToClass
                       .WithIdentifier(SyntaxFactory.Identifier(NameGenerator.Combine(applyToClass.Identifier.ValueText, this.suffix)))
                       .WithLeadingTrivia(SyntaxFactory.Comment($"// Bogus content: {new Bogus.Faker().Hacker.Phrase()}"));
            }

            if (copy != null)
            {
                results = results.Add(copy);
            }

            return(Task.FromResult(results));
        }
示例#12
0
 private static bool TryGetBackingMember(ObjectCreationExpressionSyntax objectCreation, SyntaxNodeAnalysisContext context, out FieldOrProperty fieldOrProperty, [NotNullWhen(true)] out MemberDeclarationSyntax?memberDeclaration)
 {
     fieldOrProperty   = default;
     memberDeclaration = null;
     return(objectCreation.Parent switch
     {
         EqualsValueClauseSyntax _ => objectCreation.TryFirstAncestor(out memberDeclaration) &&
         FieldOrProperty.TryCreate(context.ContainingSymbol, out fieldOrProperty),
         ArrowExpressionClauseSyntax _ => objectCreation.TryFirstAncestor(out memberDeclaration) &&
         context.ContainingSymbol is IMethodSymbol {
             AssociatedSymbol : { } associatedSymbol
         } &&
示例#13
0
            public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
            {
                if (!node.AttributeLists.Any())
                {
                    base.VisitMethodDeclaration(node);
                    return;
                }

                var attribute = node.AttributeLists
                                .SelectMany(al => al.Attributes)
                                .SingleOrDefault(attr => attr.Name.ToString() == "JsonParseMethod");

                if (attribute is null)
                {
                    base.VisitMethodDeclaration(node);
                    return;
                }

                var semanticModel = Compilation.GetSemanticModel(node.SyntaxTree);

                var type       = node.Ancestors().OfType <TypeDeclarationSyntax>().First();
                var typeName   = type.ToTypeName(semanticModel);
                var typeSymbol = semanticModel.GetDeclaredSymbol(type);

                if (node.ReturnType.ToTypeName(semanticModel) != typeName)
                {
                    throw new InvalidOperationException($"Parse method {typeName}.{node.Identifier} must have a signature returning the containing type.");
                }

                if (node.ParameterList.Parameters.Count != 1)
                {
                    throw new InvalidOperationException($"Parse method {typeName}.{node.Identifier} must have a single parameter");
                }

                if (node.Modifiers.Any(m => m.ToString() == "private" || m.ToString() == "internal"))
                {
                    throw new InvalidOperationException($"Parse method {typeName}.{node.Identifier} must have be public or internal");
                }

                if (!node.Modifiers.Any(m => m.ToString() == "static"))
                {
                    throw new InvalidOperationException($"Parse method {typeName}.{node.Identifier} must have be static");
                }

                var parseType = node.ParameterList.Parameters.Single().Type !.ToTypeName(semanticModel);

                var writeMemberName = attribute.ArgumentList?.Arguments.SingleOrDefault();
                Func <ImmutableDictionary <TypeName, JsonType>, string, string>?writeStatement = null;
                MemberDeclarationSyntax?outputMember = null;

                if (writeMemberName is not null)
                {
                    if (writeMemberName.Expression is null)
                    {
                        throw new InvalidOperationException("JsonParseMethod declarations must have zero arguments or a single unnamed nameof parameter naming the write member");
                    }

                    if (writeMemberName.Expression is not InvocationExpressionSyntax invocation || invocation.Expression.ToString() != "nameof")
                    {
                        throw new InvalidOperationException("JsonParseMethod declarations that specify a write member must use nameof to reference the member");
                    }

                    if (invocation.ArgumentList.Arguments.Count != 1 || invocation.ArgumentList.Arguments.Single().Expression is null)
                    {
                        throw new InvalidOperationException("Invalid nameof operator");
                    }

                    var symbolInfo = semanticModel.GetSymbolInfo(invocation.ArgumentList.Arguments.Single().Expression);
                    var symbol     = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.OfType <IMethodSymbol>().SingleOrDefault(m => m.Parameters.Length == 0 && !m.ReturnsVoid && !m.IsStatic && SymbolEqualityComparer.Default.Equals(m.ContainingType, typeSymbol));

                    if (symbol is IMethodSymbol method)
                    {
                        var writeOutputType = method.ReturnType.ToTypeName();
                        writeStatement = (jsonTypes, valueExpr) => jsonTypes.TryGetValue(writeOutputType, out var parseTypeJsonType) && parseTypeJsonType.CanDirectWrite(jsonTypes) ? parseTypeJsonType.DirectWriteStatement !(jsonTypes, $"({valueExpr}).{method.Name}()") : null;
                        outputMember   = method.DeclaringSyntaxReferences.First().GetSyntax() as MemberDeclarationSyntax;
                    }
                    else if (symbol is IPropertySymbol property)
                    {
                        var writeOutputType = property.Type.ToTypeName();
                        writeStatement = (jsonTypes, valueExpr) => jsonTypes.TryGetValue(writeOutputType, out var parseTypeJsonType) && parseTypeJsonType.CanDirectWrite(jsonTypes) ? parseTypeJsonType.DirectWriteStatement !(jsonTypes, $"({valueExpr}).{property.Name}") : null;
                        outputMember   = property.DeclaringSyntaxReferences.First().GetSyntax() as MemberDeclarationSyntax;
                    }
                    else
                    {
                        throw new InvalidOperationException($"The member {invocation.ArgumentList.Arguments.Single().Expression} is not an instance property or method with no parameters and a return value on the same type as the parse method.");
                    }
                }

                                #pragma warning disable CS8603 // Possible null reference return.
                JsonTypes.Add(typeName, new JsonType(
                                  type: typeName,
                                  directReadExpression: jsonTypes => jsonTypes.TryGetValue(parseType, out var parseTypeJsonType) && parseTypeJsonType.CanDirectRead(jsonTypes) ? $"{typeName}.{node.Identifier}({parseTypeJsonType.DirectReadExpression!(jsonTypes)})" : null,
                                  directWriteStatement: writeStatement,
                                  converterName: $"{typeName.ShortName}MethodConverter",
                                  constructionMember: node,
                                  outputMember: outputMember,
                                  tinyType: null
                                  ));
                                #pragma warning restore CS8603 // Possible null reference return.
            }
示例#14
0
        /// <summary>
        /// Try to get the single declaration of a property.
        /// </summary>
        /// <param name="event">The <see cref="IEventSymbol"/>. </param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
        /// <param name="declaration">The declaration.</param>
        /// <returns>True if one declaration was found.</returns>
        public static bool TrySingleDeclaration(this IEventSymbol @event, CancellationToken cancellationToken, [NotNullWhen(true)] out MemberDeclarationSyntax?declaration)
        {
            if (@event is null)
            {
                throw new System.ArgumentNullException(nameof(@event));
            }

            declaration = @event.DeclaringSyntaxReferences.TrySingle(out var reference)
                ? reference.GetSyntax(cancellationToken) as MemberDeclarationSyntax
                : null;

            return(declaration != null);
        }
示例#15
0
        public void Generate()
        {
            bool hasChildrenProperty = false;

            var destinationStaticMembers = new List <MemberDeclarationSyntax>();
            var destinationMembers       = new List <MemberDeclarationSyntax>();
            var collectionProperties     = new List <PropertyDeclarationSyntax>();

            foreach (MemberDeclarationSyntax modelObjectMember in _sourceInterfaceDeclaration.Members)
            {
                if (!(modelObjectMember is PropertyDeclarationSyntax modelProperty))
                {
                    continue;
                }

                string           propertyName            = modelProperty.Identifier.Text;
                string           propertyDescriptorName  = propertyName + "Property";
                TypeSyntax       destinationPropertyType = ToDestinationType(modelProperty.Type);
                ExpressionSyntax defaultValue            = GetDefaultValue(modelProperty);

                bool isCollection = IsCollectionType(modelProperty.Type, out TypeSyntax collectionElementType);
                if (isCollection)
                {
                    collectionProperties.Add(modelProperty);
                }
                else
                {
                    AddPropertyDescriptor(propertyName, propertyDescriptorName, destinationPropertyType, defaultValue, destinationStaticMembers);
                }

                AddProperty(propertyName, propertyDescriptorName, destinationPropertyType, modelProperty.Type, destinationMembers);

                if (propertyName == "Children")
                {
                    hasChildrenProperty = true;
                }
            }

            // Add an annotation on the last static member, so we can later add a blank line between it and the properties that follow
            var lastStaticMemberAnnotation = new SyntaxAnnotation();
            int staticMemberCount          = destinationStaticMembers.Count;

            if (staticMemberCount > 0)
            {
                destinationStaticMembers[staticMemberCount - 1] = destinationStaticMembers[staticMemberCount - 1].WithAdditionalAnnotations(lastStaticMemberAnnotation);
            }

            ConstructorDeclarationSyntax?constructor = CreateConstructor(collectionProperties);

            TypeSyntax?baseInterface        = _sourceInterfaceDeclaration.BaseList?.Types.FirstOrDefault()?.Type;
            TypeSyntax destinationBaseClass = GetBaseClass(baseInterface);

            List <MemberDeclarationSyntax> classMembers = new List <MemberDeclarationSyntax>();

            classMembers.AddRange(destinationStaticMembers);
            if (constructor != null)
            {
                classMembers.Add(constructor);
            }
            classMembers.AddRange(destinationMembers);

            var classDeclaration =
                ClassDeclaration(_destinationClassName.Identifier)
                .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword)))
                .WithBaseList(
                    BaseList(
                        SeparatedList <BaseTypeSyntax>(
                            new SyntaxNodeOrToken[]
            {
                SimpleBaseType(destinationBaseClass),
                Token(SyntaxKind.CommaToken),
                SimpleBaseType(IdentifierName(_interfaceName))
            })))
                .WithMembers(new SyntaxList <MemberDeclarationSyntax>(classMembers));

            if (DestinationTypeHasTypeConverterAttribute)
            {
                classDeclaration =
                    classDeclaration.WithAttributeLists(
                        SingletonList(
                            AttributeList(
                                SingletonSeparatedList(
                                    Attribute(
                                        IdentifierName("TypeConverter"))
                                    .WithArgumentList(
                                        AttributeArgumentList(
                                            SingletonSeparatedList(
                                                AttributeArgument(
                                                    TypeOfExpression(
                                                        IdentifierName($"{_destinationClassName.Identifier}TypeConverter"))))))))));
            }

            // Add the [ContentProperty("Children")] attribute, if needed
            if (hasChildrenProperty)
            {
                classDeclaration = classDeclaration
                                   .WithAttributeLists(
                    SingletonList(
                        AttributeList(
                            SingletonSeparatedList(
                                Attribute(
                                    IdentifierName("ContentProperty"))
                                .WithArgumentList(
                                    AttributeArgumentList(
                                        SingletonSeparatedList(
                                            AttributeArgument(
                                                LiteralExpression(
                                                    SyntaxKind.StringLiteralExpression,
                                                    Literal("Children"))))))))));
            }

#if false
            var usings = new List <UsingDirectiveSyntax>
            {
                UsingDirective(_interfaceNamespaceName)
                .WithUsingKeyword(
                    Token(
                        TriviaList(
                            Comment($"// This file is generated from {_interfaceName}.cs. Update the source file to change its contents."),
                            CarriageReturnLineFeed),
                        SyntaxKind.UsingKeyword,
                        TriviaList())),
                UsingDirective(QualifiedName(IdentifierName("System"), IdentifierName("Windows")))
            };
            if (addCollectionsUsing)
            {
                usings.Add(UsingDirective(QualifiedName(
                                              QualifiedName(IdentifierName("System"), IdentifierName("Collections")),
                                              IdentifierName("Generic"))));
            }
            if (addTransformsUsing)
            {
                usings.Add(UsingDirective(QualifiedName(IdentifierName("XGraphics"), IdentifierName("Transforms"))));
                // This will be, for example, XGraphics.WPF.Transforms
                usings.Add(UsingDirective(QualifiedName(_destinationNamespaceName, IdentifierName("Transforms"))));
            }
            if (hasChildrenProperty)
            {
                usings.Add(UsingDirective(QualifiedName(
                                              QualifiedName(IdentifierName("System"), IdentifierName("Windows")),
                                              IdentifierName("Markup"))));
            }
#endif
            SyntaxList <UsingDirectiveSyntax> usingDeclarations = CreateUsingDeclarations(destinationStaticMembers.Count > 0);

            var compilationUnit =
                CompilationUnit()
                .WithUsings(usingDeclarations)
                .WithMembers(
                    SingletonList <MemberDeclarationSyntax>(
                        NamespaceDeclaration(_destinationNamespaceName)
                        .WithMembers(SingletonList <MemberDeclarationSyntax>(classDeclaration))))
                .NormalizeWhitespace();

            MemberDeclarationSyntax?lastStaticMember = compilationUnit.DescendantNodes()
                                                       .OfType <MemberDeclarationSyntax>().FirstOrDefault(n => n.HasAnnotation(lastStaticMemberAnnotation));
            if (lastStaticMember != null)
            {
                var newTrailingTrivia = lastStaticMember.GetTrailingTrivia().Add(CarriageReturnLineFeed);
                compilationUnit = compilationUnit.ReplaceNode(lastStaticMember,
                                                              lastStaticMember.WithTrailingTrivia(newTrailingTrivia));
            }

            SourceText destinationSourceText = compilationUnit.GetText();

            string outputDirectory = GetOutputDirectory(_sourceNamespaceName);
            Directory.CreateDirectory(outputDirectory);

            string destinationFilePath = Path.Combine(outputDirectory, _destinationClassName + ".cs");
            using (StreamWriter fileWriter = File.CreateText(destinationFilePath))
                destinationSourceText.Write(fileWriter);
        }
示例#16
0
        /// <summary>
        /// Find a <see cref="EventDeclarationSyntax"/> or <see cref="EventFieldDeclarationSyntax"/> by name.
        /// </summary>
        /// <param name="type">The containing type.</param>
        /// <param name="name">The name.</param>
        /// <param name="match">The match.</param>
        /// <returns>True if a match was found.</returns>
        public static bool TryFindEvent(this TypeDeclarationSyntax type, string name, [NotNullWhen(true)] out MemberDeclarationSyntax?match)
        {
            if (type is null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (name is null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            foreach (var member in type.Members)
            {
                switch (member)
                {
                case EventDeclarationSyntax {
                        Identifier: { ValueText : { } valueText }
                } declaration
                    when valueText == name :
                    match = declaration;
                    return(true);

                case EventFieldDeclarationSyntax {
                        Declaration: { Variables : { } variables }
                } eventField
                    when variables.TrySingle(x => x.Identifier.ValueText == name, out _) :
                    match = eventField;

                    return(true);
                }
            }

            match = null;
            return(false);
        }