コード例 #1
0
        private static AttributeSyntax CreateProducesResponseTypeAttribute(CodeActionContext context, int statusCode, out bool addUsingDirective)
        {
            var statusCodeSyntax = CreateStatusCodeSyntax(context, statusCode, out addUsingDirective);

            return(SyntaxFactory.Attribute(
                       SyntaxFactory.ParseName(ApiSymbolNames.ProducesResponseTypeAttribute)
                       .WithAdditionalAnnotations(Simplifier.Annotation),
                       SyntaxFactory.AttributeArgumentList().AddArguments(
                           SyntaxFactory.AttributeArgument(statusCodeSyntax))));
        }
コード例 #2
0
        private static ExpressionSyntax CreateStatusCodeSyntax(CodeActionContext context, int statusCode, out bool addUsingDirective)
        {
            if (context.StatusCodeConstants.TryGetValue(statusCode, out var constantName))
            {
                addUsingDirective = true;
                return(SyntaxFactory.MemberAccessExpression(
                           SyntaxKind.SimpleMemberAccessExpression,
                           SyntaxFactory.ParseTypeName(ApiSymbolNames.HttpStatusCodes)
                           .WithAdditionalAnnotations(Simplifier.Annotation),
                           SyntaxFactory.IdentifierName(constantName)));
            }

            addUsingDirective = false;
            return(SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(statusCode)));
        }
コード例 #3
0
        private async Task <CodeActionContext> CreateCodeActionContext(CancellationToken cancellationToken)
        {
            var root = await _document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var semanticModel = await _document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var methodReturnStatement = (ReturnStatementSyntax)root.FindNode(_diagnostic.Location.SourceSpan);
            var methodSyntax          = methodReturnStatement.FirstAncestorOrSelf <MethodDeclarationSyntax>();
            var method = semanticModel.GetDeclaredSymbol(methodSyntax, cancellationToken);

            var symbolCache = new ApiControllerSymbolCache(semanticModel.Compilation);

            var codeActionContext = new CodeActionContext(semanticModel, symbolCache, method, methodSyntax, cancellationToken);

            return(codeActionContext);
        }
        public void SimpleTest(string expected)
        {
            var model = new CodeActionContext()
            {
                Diagnostics = new[] { new Diagnostic()
                                      {
                                          Code     = new DiagnosticCode("abcd"),
                                          Message  = "message",
                                          Range    = new Range(new Position(1, 1), new Position(2, 2)),
                                          Severity = DiagnosticSeverity.Error,
                                          Source   = "csharp"
                                      } }
            };
            var result = Fixture.SerializeObject(model);

            result.Should().Be(expected);

            var deresult = new Serializer(ClientVersion.Lsp3).DeserializeObject <CodeActionContext>(expected);

            deresult.Should().BeEquivalentTo(model);
        }
コード例 #5
0
    private async Task <CodeActionContext?> CreateCodeActionContext(CancellationToken cancellationToken)
    {
        var root = await _document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

        var semanticModel = await _document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

        var diagnosticNode = root.FindNode(_diagnostic.Location.SourceSpan);
        var methodSyntax   = diagnosticNode.FirstAncestorOrSelf <MethodDeclarationSyntax>();
        var method         = semanticModel.GetDeclaredSymbol(methodSyntax, cancellationToken);

        var statusCodesType     = semanticModel.Compilation.GetTypeByMetadataName(ApiSymbolNames.HttpStatusCodes);
        var statusCodeConstants = GetStatusCodeConstants(statusCodesType);

        if (!ApiControllerSymbolCache.TryCreate(semanticModel.Compilation, out var symbolCache))
        {
            return(null);
        }

        var codeActionContext = new CodeActionContext(semanticModel, symbolCache, method, methodSyntax, statusCodeConstants, cancellationToken);

        return(codeActionContext);
    }
コード例 #6
0
        private ICollection <int> CalculateStatusCodesToApply(CodeActionContext context, IList <DeclaredApiResponseMetadata> declaredResponseMetadata)
        {
            if (!SymbolApiResponseMetadataProvider.TryGetActualResponseMetadata(context.SymbolCache, context.SemanticModel, context.MethodSyntax, context.CancellationToken, out var actualResponseMetadata))
            {
                // If we cannot parse metadata correctly, don't offer fixes.
                return(Array.Empty <int>());
            }

            var statusCodes = new HashSet <int>();

            foreach (var metadata in actualResponseMetadata)
            {
                if (DeclaredApiResponseMetadata.TryGetDeclaredMetadata(declaredResponseMetadata, metadata, result: out var declaredMetadata) &&
                    declaredMetadata.AttributeSource == context.Method)
                {
                    // A ProducesResponseType attribute is declared on the method for the current status code.
                    continue;
                }

                statusCodes.Add(metadata.IsDefaultResponse ? 200 : metadata.StatusCode);
            }

            return(statusCodes);
        }
コード例 #7
0
        public IAsyncOperation <CodeActionList> ProvideCodeActionsAsync(IModel model, Range range, CodeActionContext context)
        {
            /// Will be called whenever the caret moves, you'll get the range update.
            /// Should determine which suggestions to make for that spot.
            /// Use in combination with Markers in the editor to show squiggles on trouble spots.
            return(AsyncInfo.Run(async delegate(CancellationToken cancellationToken)
            {
                // In the warning squiggle.
                if (IsOn && _targetRange.ContainsRange(range))
                {
                    return new CodeActionList()
                    {
                        Actions = new CodeAction[] {
                            new CodeAction()
                            {
                                Title = "Suggested Quick Fix",
                                Kind = "quickfix",
                                // If a Command and an Edit are provided the Command happens after the edit, you don't have to provide both though.
                                Command = new Command()
                                {
                                    Id = _commandId,
                                    Title = "Suggestion Command",
                                    Arguments = new object[] { "Suggestion Info" },
                                    Tooltip = "This is a CodeAction Command"
                                },
                                Diagnostics = new IMarkerData[]
                                {
                                    new MarkerData(_targetRange)
                                    {
                                        Code = "2344",
                                        Message = "This is a \"Warning\" about 'that thing'.",
                                        Severity = MarkerSeverity.Warning,
                                        Source = "Origin",
                                    }
                                },
                                // TODO: We should write an extension method helper to create one of these easier maybe?
                                Edit = new WorkspaceEdit()
                                {
                                    Edits = new WorkspaceTextEdit[]
                                    {
                                        new WorkspaceTextEdit()
                                        {
                                            //// Unlike Monaco, we only track one model, so we don't have to pass a resource uri here.
                                            Edit = new TextEdit()
                                            {
                                                Text = "Done",
                                                Range = _targetRange
                                            }
                                        }
                                    }
                                },
                            }
                        }
                    };
                }

                return new CodeActionList();
            }));
        }