예제 #1
0
        private void CreateDelegateDeclaration(Document document, FuncOrAction funcOrAction, IParameterSymbol parameterSymbol, out string newDelegateName, out DelegateDeclarationSyntax delegateDeclaration)
        {
            var syntaxGenerator = SyntaxGenerator.GetGenerator(document);

            var parameters = funcOrAction switch
            {
                FuncOrAction.Action action => action.Parameters,
                FuncOrAction.Func func => func.Parameters,
                _ => throw new System.NotImplementedException()
            };

            newDelegateName     = MakeFirstLetterUpperCase(parameterSymbol.Name);
            delegateDeclaration = (DelegateDeclarationSyntax)syntaxGenerator.DelegateDeclaration(
                newDelegateName,
                parameters
                .Select(p => syntaxGenerator.ParameterDeclaration(
                            p.Name,
                            syntaxGenerator.TypeExpression(p.Type))),
                accessibility: Accessibility.Public);
            if (funcOrAction is FuncOrAction.Func func1)
            {
                delegateDeclaration = delegateDeclaration
                                      .WithReturnType((TypeSyntax)syntaxGenerator.TypeExpression(func1.ReturnType));
            }
        }
예제 #2
0
        private async Task <Solution> UpdateSolutionToAddAndUseANewDelegate(
            Document document,
            FuncOrAction funcOrAction,
            ParameterSyntax parameterSyntax,
            IParameterSymbol parameterSymbol,
            SemanticModel semanticModel)
        {
            CreateDelegateDeclaration(
                document,
                funcOrAction,
                parameterSymbol,
                out var newDelegateName,
                out var delegateDeclaration);

            var method = (MethodDeclarationSyntax)parameterSyntax.Parent.Parent;

            var annotationForParameter = new SyntaxAnnotation();

            var updatedMethod = method.ReplaceNode(parameterSyntax,
                                                   parameterSyntax
                                                   .WithType(
                                                       SyntaxFactory.IdentifierName(newDelegateName))
                                                   .WithAdditionalAnnotations(annotationForParameter));

            var root = await document.GetSyntaxRootAsync();

            var containingType = (TypeDeclarationSyntax)method.Parent;

            var containingTypeSymbol = semanticModel.GetDeclaredSymbol(containingType);

            var syntaxGenerator = SyntaxGenerator.GetGenerator(document);

            var qualifiedDelegateType = SyntaxFactory.QualifiedName(
                (NameSyntax)syntaxGenerator.TypeExpression(containingTypeSymbol),
                SyntaxFactory.IdentifierName(newDelegateName));

            var indexOfMethodWithinSiblingMembers = containingType.Members.IndexOf(method);

            var solution = document.Project.Solution;

            var updatedRoot = root.ReplaceNodes(new SyntaxNode[] { method, containingType },
                                                (originalNode, possiblyChangedNode) =>
            {
                if (originalNode == method)
                {
                    return(updatedMethod);
                }
                else if (originalNode == containingType)
                {
                    var possibleChangedContainingType = (TypeDeclarationSyntax)possiblyChangedNode;

                    var newMembers = possibleChangedContainingType.Members.Insert(
                        indexOfMethodWithinSiblingMembers,
                        delegateDeclaration);

                    return(possibleChangedContainingType
                           .WithMembers(SyntaxFactory.List(newMembers))
                           .NormalizeWhitespace());
                }

                throw new System.Exception("Unexpected: originalNode is not any of the nodes passed to ReplaceNodes");
            });

            solution = solution.WithDocumentSyntaxRoot(document.Id, updatedRoot);

            var newDocument = solution.GetDocument(document.Id);

            var newSemanticModel = await newDocument.GetSemanticModelAsync();

            var newDocumentRootNode = await newDocument.GetSyntaxRootAsync();

            var newParameterSyntax =
                (ParameterSyntax)newDocumentRootNode.GetAnnotatedNodes(annotationForParameter).Single();

            var newParameterSymbol = newSemanticModel.GetDeclaredSymbol(newParameterSyntax);

            var parametersThatAreSourcesOfParameter = await FindSourceParameters(
                newParameterSymbol,
                solution);

            foreach (var callerParameterAndDocument in parametersThatAreSourcesOfParameter)
            {
                var callerDocument = callerParameterAndDocument.document;

                var callerDocumentRoot = await callerDocument.GetSyntaxRootAsync();

                var callerParameterSyntax = (ParameterSyntax)callerDocumentRoot.FindNode(
                    callerParameterAndDocument.parameter.Locations.Single().SourceSpan);

                var newParameterType = callerDocument.Id == document.Id
                    ? (TypeSyntax)SyntaxFactory.IdentifierName(newDelegateName)
                    : qualifiedDelegateType;

                var updatedCallerParameterSyntax = callerParameterSyntax.WithType(newParameterType);

                var updatedCallerDocumentRoot = callerDocumentRoot
                                                .ReplaceNode(callerParameterSyntax, updatedCallerParameterSyntax);

                solution = solution.WithDocumentSyntaxRoot(callerDocument.Id, updatedCallerDocumentRoot);
            }


            return(solution);
        }
예제 #3
0
        private async Task <Solution> UpdateSolutionToAddAndUseANewDelegate(
            Document document,
            FuncOrAction funcOrAction,
            ParameterSyntax parameterSyntax,
            IParameterSymbol parameterSymbol,
            SemanticModel semanticModel)
        {
            var allChanges = new Dictionary <DocumentId, ChangesForDocument>();

            void AddChange(DocumentId documentId, Change change)
            {
                if (allChanges.TryGetValue(documentId, out var changes))
                {
                    allChanges[documentId] = changes.Add(change);
                }
                else
                {
                    allChanges[documentId] = new ChangesForDocument(documentId, ImmutableArray.Create(change));
                }
            }

            CreateDelegateDeclaration(
                document,
                funcOrAction,
                parameterSymbol,
                out var newDelegateName,
                out var delegateDeclaration);

            var method = (MethodDeclarationSyntax)parameterSyntax.Parent.Parent;

            var containingType = (TypeDeclarationSyntax)method.Parent;

            var indexOfMethodWithinSiblingMembers = containingType.Members.IndexOf(method);

            var changeToAddDelegate = new Change(containingType, x =>
            {
                var possibleChangedContainingType = (TypeDeclarationSyntax)x;

                var newMembers = possibleChangedContainingType.Members.Insert(
                    indexOfMethodWithinSiblingMembers,
                    delegateDeclaration);

                return(possibleChangedContainingType
                       .WithMembers(SyntaxFactory.List(newMembers))
                       .NormalizeWhitespace());
            });

            AddChange(document.Id, changeToAddDelegate);

            var annotationForParameter = new SyntaxAnnotation();

            var changeToParameter = new Change(parameterSyntax, x =>
            {
                var potentiallyChangedParameter = (ParameterSyntax)x;

                return(potentiallyChangedParameter
                       .WithType(
                           SyntaxFactory.IdentifierName(newDelegateName)));
            });

            AddChange(document.Id, changeToParameter);

            var containingTypeSymbol = semanticModel.GetDeclaredSymbol(containingType);

            var syntaxGenerator = SyntaxGenerator.GetGenerator(document);

            var qualifiedDelegateType = SyntaxFactory.QualifiedName(
                (NameSyntax)syntaxGenerator.TypeExpression(containingTypeSymbol),
                SyntaxFactory.IdentifierName(newDelegateName));

            var parametersThatAreSourcesOfParameter = await FindSourceParameters(
                parameterSymbol,
                document.Project.Solution);

            foreach (var callerParameterAndDocument in parametersThatAreSourcesOfParameter)
            {
                var callerDocument = callerParameterAndDocument.document;

                var callerDocumentRoot = await callerDocument.GetSyntaxRootAsync();

                var callerParameterSyntax = (ParameterSyntax)callerDocumentRoot.FindNode(
                    callerParameterAndDocument.parameter.Locations.Single().SourceSpan);

                var newParameterType = callerDocument.Id == document.Id
                    ? (TypeSyntax)SyntaxFactory.IdentifierName(newDelegateName)
                    : qualifiedDelegateType;

                var change = new Change(callerParameterSyntax, x =>
                {
                    var potentiallyChangedParameterSyntax = (ParameterSyntax)x;
                    return(potentiallyChangedParameterSyntax.WithType(newParameterType));
                });

                AddChange(callerDocument.Id, change);
            }

            var changes = allChanges.Values.ToImmutableArray();

            return(await ApplyChanges(document.Project.Solution, changes));
        }
예제 #4
0
        private async Task <Document> UpdateDocumentToAddAndUseANewDelegate(
            Document document,
            FuncOrAction funcOrAction,
            ParameterSyntax parameterSyntax,
            IParameterSymbol parameterSymbol,
            SemanticModel semanticModel)
        {
            var syntaxGenerator = SyntaxGenerator.GetGenerator(document);

            var parameters = funcOrAction switch
            {
                FuncOrAction.Action action => action.Parameters,
                FuncOrAction.Func func => func.Parameters,
                _ => throw new System.NotImplementedException()
            };

            var newDelegateName = MakeFirstLetterUpperCase(parameterSymbol.Name);

            var delegateDeclaration = (DelegateDeclarationSyntax)syntaxGenerator.DelegateDeclaration(
                newDelegateName,
                parameters
                .Select(p => syntaxGenerator.ParameterDeclaration(
                            p.Name,
                            syntaxGenerator.TypeExpression(p.Type))),
                accessibility: Accessibility.Public);

            if (funcOrAction is FuncOrAction.Func func1)
            {
                delegateDeclaration = delegateDeclaration
                                      .WithReturnType((TypeSyntax)syntaxGenerator.TypeExpression(func1.ReturnType));
            }

            var method = (MethodDeclarationSyntax)parameterSyntax.Parent.Parent;

            var updatedMethod = method.ReplaceNode(parameterSyntax.Type,
                                                   SyntaxFactory.IdentifierName(newDelegateName));

            var root = await document.GetSyntaxRootAsync();

            var containingType = (TypeDeclarationSyntax)method.Parent;

            var indexOfMethodWithinSiblingMembers = containingType.Members.IndexOf(method);

            var updatedRoot = root.ReplaceNodes(new SyntaxNode[] { method, containingType },
                                                (originalNode, possiblyChangedNode) =>
            {
                if (originalNode == method)
                {
                    return(updatedMethod);
                }
                else if (originalNode == containingType)
                {
                    var possibleChangedContainingType = (TypeDeclarationSyntax)possiblyChangedNode;

                    var newMembers = possibleChangedContainingType.Members.Insert(
                        indexOfMethodWithinSiblingMembers,
                        delegateDeclaration);

                    return(possibleChangedContainingType.WithMembers(SyntaxFactory.List(newMembers)));
                }

                throw new System.Exception("Unexpected: originalNode is not any of the nodes passed to ReplaceNodes");
            });

            return(document.WithSyntaxRoot(updatedRoot));
        }