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)))); }
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))); }
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); }
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); }
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); }
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(); })); }