public static async Task <RemoveSuppressionCodeAction> CreateAsync( SuppressionTargetInfo suppressionTargetInfo, Document documentOpt, Project project, Diagnostic diagnostic, AbstractSuppressionCodeFixProvider fixer, CancellationToken cancellationToken) { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var attribute = diagnostic.GetSuppressionInfo(compilation).Attribute; if (attribute != null) { return(AttributeRemoveAction.Create(attribute, project, diagnostic, fixer)); } else if (documentOpt != null && !SuppressionHelpers.IsSynthesizedExternalSourceDiagnostic(diagnostic)) { var options = await SyntaxFormattingOptions.FromDocumentAsync(documentOpt, cancellationToken).ConfigureAwait(false); return(PragmaRemoveAction.Create(suppressionTargetInfo, documentOpt, options, diagnostic, fixer)); } else { return(null); } }
private async Task <Solution> RemoveUnnecessaryImportsAsync( Solution solution, DocumentId sourceDocumentId, DocumentId documentWithMovedTypeId) { var documentWithMovedType = solution.GetRequiredDocument(documentWithMovedTypeId); var documentWithMovedTypeFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(documentWithMovedType, CancellationToken).ConfigureAwait(false); var syntaxFacts = documentWithMovedType.GetRequiredLanguageService <ISyntaxFactsService>(); var removeUnnecessaryImports = documentWithMovedType.GetRequiredLanguageService <IRemoveUnnecessaryImportsService>(); // Remove all unnecessary imports from the new document we've created. documentWithMovedType = await removeUnnecessaryImports.RemoveUnnecessaryImportsAsync(documentWithMovedType, documentWithMovedTypeFormattingOptions, CancellationToken).ConfigureAwait(false); solution = solution.WithDocumentSyntaxRoot( documentWithMovedTypeId, await documentWithMovedType.GetRequiredSyntaxRootAsync(CancellationToken).ConfigureAwait(false)); // See which imports we kept around. var rootWithMovedType = await documentWithMovedType.GetRequiredSyntaxRootAsync(CancellationToken).ConfigureAwait(false); var movedImports = rootWithMovedType.DescendantNodes() .Where(syntaxFacts.IsUsingOrExternOrImport) .ToImmutableArray(); // Now remove any unnecessary imports from the original doc that moved to the new doc. var sourceDocument = solution.GetRequiredDocument(sourceDocumentId); var sourceDocumentFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(sourceDocument, CancellationToken).ConfigureAwait(false); sourceDocument = await removeUnnecessaryImports.RemoveUnnecessaryImportsAsync( sourceDocument, n => movedImports.Contains(i => syntaxFacts.AreEquivalent(i, n)), sourceDocumentFormattingOptions, CancellationToken).ConfigureAwait(false); return(solution.WithDocumentSyntaxRoot( sourceDocumentId, await sourceDocument.GetRequiredSyntaxRootAsync(CancellationToken).ConfigureAwait(false))); }
public static async Task <Document> AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, CancellationToken cancellationToken) { var service = document.GetRequiredLanguageService <IMetadataAsSourceService>(); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); return(await service.AddSourceToAsync(document, symbolCompilation, symbol, formattingOptions, cancellationToken).ConfigureAwait(false)); }
/// <summary> /// Clean up the provided spans in the document. /// Optionally you can provide your own options and code cleaners. Otherwise, the default will be used. /// </summary> public static async Task <Document> CleanupAsync(Document document, ImmutableArray <TextSpan> spans, ImmutableArray <ICodeCleanupProvider> providers = default, CancellationToken cancellationToken = default) { var cleanupService = document.GetRequiredLanguageService <ICodeCleanerService>(); var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); return(await cleanupService.CleanupAsync(document, spans, options, providers, cancellationToken).ConfigureAwait(false)); }
protected override async Task <Document> GetChangedSuppressionDocumentAsync(CancellationToken cancellationToken) { var suppressionsDoc = await GetOrCreateSuppressionsDocumentAsync(cancellationToken).ConfigureAwait(false); var services = suppressionsDoc.Project.Solution.Workspace.Services; var suppressionsRoot = await suppressionsDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var addImportsService = suppressionsDoc.GetRequiredLanguageService <IAddImportsService>(); var options = await SyntaxFormattingOptions.FromDocumentAsync(suppressionsDoc, cancellationToken).ConfigureAwait(false); foreach (var(targetSymbol, diagnostics) in _diagnosticsBySymbol) { foreach (var diagnostic in diagnostics) { Contract.ThrowIfFalse(!diagnostic.IsSuppressed); suppressionsRoot = Fixer.AddGlobalSuppressMessageAttribute( suppressionsRoot, targetSymbol, _suppressMessageAttribute, diagnostic, services, options, addImportsService, cancellationToken); } } var result = suppressionsDoc.WithSyntaxRoot(suppressionsRoot); var final = await CleanupDocumentAsync(result, cancellationToken).ConfigureAwait(false); return(final); }
public async Task <(Document document, SyntaxToken invocationNameToken)> GetFormattedDocumentAsync(CancellationToken cancellationToken) { if (DocumentWithoutFinalFormatting is null) { throw new InvalidOperationException(); } var annotation = new SyntaxAnnotation(); var root = await DocumentWithoutFinalFormatting.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); root = root.ReplaceToken(InvocationNameToken, InvocationNameToken.WithAdditionalAnnotations(annotation)); var annotatedDocument = DocumentWithoutFinalFormatting.WithSyntaxRoot(root); var simplifiedDocument = await Simplifier.ReduceAsync(annotatedDocument, Simplifier.Annotation, optionSet : null, cancellationToken).ConfigureAwait(false); var simplifiedRoot = await simplifiedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await SyntaxFormattingOptions.FromDocumentAsync(DocumentWithoutFinalFormatting, cancellationToken).ConfigureAwait(false); var services = DocumentWithoutFinalFormatting.Project.Solution.Workspace.Services; var formattedDocument = simplifiedDocument.WithSyntaxRoot( Formatter.Format(simplifiedRoot, Formatter.Annotation, services, options, FormattingRules, cancellationToken)); var formattedRoot = await formattedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); return(formattedDocument, formattedRoot.GetAnnotatedTokens(annotation).Single()); }
internal static async Task <Document> CleanupDocumentAsync( Document document, CancellationToken cancellationToken) { if (document.SupportsSyntaxTree) { var addImportOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); document = await ImportAdder.AddImportsFromSymbolAnnotationAsync( document, Simplifier.AddImportsAnnotation, addImportOptions, cancellationToken).ConfigureAwait(false); document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false); // format any node with explicit formatter annotation document = await Formatter.FormatAsync(document, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); // format any elastic whitespace document = await Formatter.FormatAsync(document, SyntaxAnnotation.ElasticAnnotation, formattingOptions, cancellationToken).ConfigureAwait(false); document = await CaseCorrector.CaseCorrectAsync(document, CaseCorrector.Annotation, cancellationToken).ConfigureAwait(false); } return(document); }
private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch) { var document = buffer.CurrentSnapshot.GetRelatedDocumentsWithChanges().First(); var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(); var line = root.GetText().Lines[indentationLine]; var index = line.ToString().LastIndexOf(ch); Assert.InRange(index, 0, int.MaxValue); // get token var position = line.Start + index; var token = root.FindToken(position); var formattingRuleProvider = workspace.Services.GetService <IHostDependentFormattingRuleFactoryService>(); var rules = ImmutableArray.Create(formattingRuleProvider.CreateRule(document, position)).AddRange(Formatter.GetDefaultFormattingRules(document)); var options = new IndentationOptions( await SyntaxFormattingOptions.FromDocumentAsync(document, CancellationToken.None).ConfigureAwait(false), AutoFormattingOptions.Default); var formatter = new CSharpSmartTokenFormatter(options, rules, root); var changes = await formatter.FormatTokenAsync(token, CancellationToken.None); ApplyChanges(buffer, changes); }
private static async Task <Document> AddUsingDirectivesAsync( Document document, SyntaxNode root, BaseNamespaceDeclarationSyntax namespaceDeclaration, CancellationToken cancellationToken) { var addImportsService = document.GetRequiredLanguageService <IAddImportsService>(); var removeImportsService = document.GetRequiredLanguageService <IRemoveUnnecessaryImportsService>(); var annotation = new SyntaxAnnotation(); using var _ = ArrayBuilder <UsingDirectiveSyntax> .GetInstance(out var directives); AddUsingDirectives(namespaceDeclaration.Name, annotation, directives); var generator = document.GetRequiredLanguageService <SyntaxGenerator>(); var addImportOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var documentWithImportsAdded = document.WithSyntaxRoot(addImportsService.AddImports( compilation: null !, root, contextLocation: null, directives, generator, addImportOptions, cancellationToken)); return(await removeImportsService.RemoveUnnecessaryImportsAsync( documentWithImportsAdded, n => n.HasAnnotation(annotation), formattingOptions, cancellationToken).ConfigureAwait(false)); }
private static async Task <Document> RemoveUnnecessaryImportsAsync( Document document, CancellationToken cancellationToken) { var service = document.GetLanguageService <IRemoveUnnecessaryImportsService>(); var syntaxFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); return(await service.RemoveUnnecessaryImportsAsync(document, syntaxFormattingOptions, cancellationToken).ConfigureAwait(false)); }
// TODO: move to LSP layer public static async Task <IndentationOptions> GetIndentationOptionsAsync(this IGlobalOptionService globalOptions, Document document, CancellationToken cancellationToken) { var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var autoFormattingOptions = globalOptions.GetAutoFormattingOptions(document.Project.Language); var indentStyle = globalOptions.GetOption(SmartIndent, document.Project.Language); return(new(formattingOptions, autoFormattingOptions, indentStyle)); }
protected override async Task<Document> GetChangedSuppressionDocumentAsync(CancellationToken cancellationToken) { var suppressionsDoc = await GetOrCreateSuppressionsDocumentAsync(cancellationToken).ConfigureAwait(false); var services = suppressionsDoc.Project.Solution.Workspace.Services; var suppressionsRoot = await suppressionsDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var addImportsService = suppressionsDoc.GetRequiredLanguageService<IAddImportsService>(); var options = await SyntaxFormattingOptions.FromDocumentAsync(suppressionsDoc, cancellationToken).ConfigureAwait(false); suppressionsRoot = Fixer.AddGlobalSuppressMessageAttribute( suppressionsRoot, _targetSymbol, _suppressMessageAttribute, _diagnostic, services, options, addImportsService, cancellationToken); return suppressionsDoc.WithSyntaxRoot(suppressionsRoot); }
protected override async Task <Document> PostProcessChangesAsync(Document document, CancellationToken cancellationToken) { var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false); document = await Formatter.FormatAsync(document, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); document = await CaseCorrector.CaseCorrectAsync(document, CaseCorrector.Annotation, cancellationToken).ConfigureAwait(false); return(document); }
protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken) { using var _ = ArrayBuilder <IMethodSymbol> .GetInstance(out var methods); if (_generateEquals) { methods.Add(await CreateEqualsMethodAsync(cancellationToken).ConfigureAwait(false)); } var constructedTypeToImplement = await GetConstructedTypeToImplementAsync(cancellationToken).ConfigureAwait(false); if (constructedTypeToImplement is object) { methods.Add(await CreateIEquatableEqualsMethodAsync(constructedTypeToImplement, cancellationToken).ConfigureAwait(false)); } if (_generateGetHashCode) { methods.Add(await CreateGetHashCodeMethodAsync(cancellationToken).ConfigureAwait(false)); } if (_generateOperators) { await AddOperatorsAsync(methods, cancellationToken).ConfigureAwait(false); } var codeGenerator = _document.GetRequiredLanguageService <ICodeGenerationService>(); var codeGenOptions = await CodeGenerationOptions.FromDocumentAsync(CodeGenerationContext.Default, _document, cancellationToken).ConfigureAwait(false); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(_document, cancellationToken).ConfigureAwait(false); var newTypeDeclaration = codeGenerator.AddMembers(_typeDeclaration, methods, codeGenOptions, cancellationToken); if (constructedTypeToImplement is object) { var generator = _document.GetRequiredLanguageService <SyntaxGenerator>(); newTypeDeclaration = generator.AddInterfaceType(newTypeDeclaration, generator.TypeExpression(constructedTypeToImplement)); } var newDocument = await UpdateDocumentAndAddImportsAsync( _typeDeclaration, newTypeDeclaration, cancellationToken).ConfigureAwait(false); var service = _document.GetRequiredLanguageService <IGenerateEqualsAndGetHashCodeService>(); var formattedDocument = await service.FormatDocumentAsync( newDocument, formattingOptions, cancellationToken).ConfigureAwait(false); return(formattedDocument); }
private int FormatWorker(IVsTextLayer textLayer, TextSpan[] selections, CancellationToken cancellationToken) { var textBuffer = this.EditorAdaptersFactoryService.GetDataBuffer((IVsTextBuffer)textLayer); if (textBuffer == null) { return(VSConstants.E_UNEXPECTED); } var document = textBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return(VSConstants.E_FAIL); } var root = document.GetSyntaxRootSynchronously(cancellationToken); var text = root.SyntaxTree.GetText(cancellationToken); var options = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); var ts = selections.Single(); var start = text.Lines[ts.iStartLine].Start + ts.iStartIndex; var end = text.Lines[ts.iEndLine].Start + ts.iEndIndex; var adjustedSpan = GetFormattingSpan(root, start, end); // Since we know we are on the UI thread, lets get the base indentation now, so that there is less // cleanup work to do later in Venus. var ruleFactory = Workspace.Services.GetService <IHostDependentFormattingRuleFactoryService>(); var rules = ruleFactory.CreateRule(document, start).Concat(Formatter.GetDefaultFormattingRules(document)); // use formatting that return text changes rather than tree rewrite which is more expensive var formatter = document.GetRequiredLanguageService <ISyntaxFormattingService>(); var originalChanges = formatter.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(adjustedSpan), options, rules, cancellationToken) .GetTextChanges(cancellationToken); var originalSpan = RoslynTextSpan.FromBounds(start, end); var formattedChanges = ruleFactory.FilterFormattedChanges(document, originalSpan, originalChanges); if (formattedChanges.IsEmpty()) { return(VSConstants.S_OK); } // create new formatted document var formattedDocument = document.WithText(text.WithChanges(formattedChanges)); Workspace.ApplyDocumentChanges(formattedDocument, cancellationToken); return(VSConstants.S_OK); }
private static Document Format(ICommentSelectionService service, ITextSnapshot snapshot, IEnumerable <SnapshotSpan> changes, CancellationToken cancellationToken) { var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return(null); } var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); var textSpans = changes.SelectAsArray(change => change.Span.ToTextSpan()); return(service.FormatAsync(document, textSpans, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken)); }
private static async Task <Document> RemoveUnnecessaryImportsAsync( #endif Document document, CancellationToken cancellationToken) { #if CODE_STYLE var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var formattingOptions = GetSyntaxFormatting().GetFormattingOptions(document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree)); #else var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); #endif var service = document.GetRequiredLanguageService <IRemoveUnnecessaryImportsService>(); return(await service.RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).ConfigureAwait(false)); }
public async Task <Document> AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, CancellationToken cancellationToken) { if (document == null) { throw new ArgumentNullException(nameof(document)); } var newSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var rootNamespace = newSemanticModel.GetEnclosingNamespace(0, cancellationToken); var context = new CodeGenerationContext( contextLocation: newSemanticModel.SyntaxTree.GetLocation(new TextSpan()), generateMethodBodies: false, generateDocumentationComments: true, mergeAttributes: false, autoInsertionLocation: false); // Add the interface of the symbol to the top of the root namespace document = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync( document.Project.Solution, rootNamespace, CreateCodeGenerationSymbol(document, symbol), context, cancellationToken).ConfigureAwait(false); document = await AddNullableRegionsAsync(document, cancellationToken).ConfigureAwait(false); var docCommentFormattingService = document.GetLanguageService <IDocumentationCommentFormattingService>(); var docWithDocComments = await ConvertDocCommentsToRegularCommentsAsync(document, docCommentFormattingService, cancellationToken).ConfigureAwait(false); var docWithAssemblyInfo = await AddAssemblyInfoRegionAsync(docWithDocComments, symbolCompilation, symbol.GetOriginalUnreducedDefinition(), cancellationToken).ConfigureAwait(false); var node = await docWithAssemblyInfo.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await SyntaxFormattingOptions.FromDocumentAsync(docWithAssemblyInfo, cancellationToken).ConfigureAwait(false); var formattedDoc = await Formatter.FormatAsync( docWithAssemblyInfo, SpecializedCollections.SingletonEnumerable(node.FullSpan), options, GetFormattingRules(docWithAssemblyInfo), cancellationToken).ConfigureAwait(false); var reducers = GetReducers(); return(await Simplifier.ReduceAsync(formattedDoc, reducers, null, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> FormatDocumentAsync(Document document, CancellationToken cancellationToken) { var node = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); // Apply formatting rules var formattedDoc = await Formatter.FormatAsync( document, SpecializedCollections.SingletonEnumerable(node.FullSpan), options, CSharpDecompiledSourceFormattingRule.Instance.Concat(Formatter.GetDefaultFormattingRules(document)), cancellationToken).ConfigureAwait(false); return(formattedDoc); }
private static async Task <Document> CleanUpNewLinesAsync(Document document, IEnumerable <TextSpan> insertSpans, CancellationToken cancellationToken) { var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var newDocument = document; // Since imports can be added at both the CompilationUnit and the Namespace level, // format each span individually so that we can retain each newline that was intended // to separate the import section from the other content. foreach (var insertSpan in insertSpans) { newDocument = await CleanUpNewLinesAsync(newDocument, insertSpan, options, cancellationToken).ConfigureAwait(false); } return(newDocument); }
protected override async Task FixAllAsync( Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); // Defer to our callback to actually make the edits for each diagnostic. In turn, it // will return 'true' if it made a multi-line conditional expression. In that case, // we'll need to explicitly format this node so we can get our special multi-line // formatting in VB and C#. var nestedEditor = new SyntaxEditor(root, document.Project.Solution.Workspace.Services); foreach (var diagnostic in diagnostics) { await FixOneAsync( document, diagnostic, nestedEditor, cancellationToken).ConfigureAwait(false); } var changedRoot = nestedEditor.GetChangedRoot(); // Get the language specific rule for formatting this construct and call into the // formatted to explicitly format things. Note: all we will format is the new // conditional expression as that's the only node that has the appropriate // annotation on it. var rules = new List <AbstractFormattingRule> { GetMultiLineFormattingRule() }; #if CODE_STYLE var provider = GetSyntaxFormattingService(); var options = provider.GetFormattingOptions(document.Project.AnalyzerOptions.GetAnalyzerOptionSet(root.SyntaxTree, cancellationToken)); #else var provider = document.Project.Solution.Workspace.Services; var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); #endif var formattedRoot = Formatter.Format(changedRoot, SpecializedFormattingAnnotation, provider, options, rules, cancellationToken); changedRoot = formattedRoot; editor.ReplaceNode(root, changedRoot); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, span, cancellationToken) = context; if (!span.IsEmpty) { return; } var position = span.Start; var root = (CompilationUnitSyntax)await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(position); var namespaceDecl = token.GetAncestor <BaseNamespaceDeclarationSyntax>(); if (namespaceDecl == null) { return; } if (!IsValidPosition(namespaceDecl, position)) { return; } var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var info = CanOfferUseBlockScoped(optionSet, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.BlockScoped) : CanOfferUseFileScoped(optionSet, root, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.FileScoped) : ((string title, string equivalenceKey)?)null; if (info == null) { return; } var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); context.RegisterRefactoring(new MyCodeAction( info.Value.title, c => ConvertAsync(document, namespaceDecl, formattingOptions, c), info.Value.equivalenceKey)); }
internal void PerformEdit(Func <Document, Document> action) { EnsureEditor(() => { Debug.Assert(_invisibleEditor != null); var document = GetDocument(); var workspace = document.Project.Solution.Workspace; var result = action(document); var formatted = State.ThreadingContext.JoinableTaskFactory.Run(async() => { var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(result, CancellationToken.None).ConfigureAwait(false); var formatted = await Formatter.FormatAsync(result, Formatter.Annotation, formattingOptions, CancellationToken.None).ConfigureAwait(true); formatted = await Formatter.FormatAsync(formatted, SyntaxAnnotation.ElasticAnnotation, formattingOptions, CancellationToken.None).ConfigureAwait(true); return(formatted); }); ApplyChanges(workspace, formatted); }); }
/// <summary> /// format given snapshot and apply text changes to buffer /// </summary> public static void FormatAndApplyToBuffer(this ITextSnapshot snapshot, TextSpan span, IEnumerable <AbstractFormattingRule>?rules, CancellationToken cancellationToken) { var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } rules = document.GetFormattingRules(span, rules); var root = document.GetRequiredSyntaxRootSynchronously(cancellationToken); var formatter = document.GetRequiredLanguageService <ISyntaxFormattingService>(); var options = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); var result = formatter.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(span), options, rules, cancellationToken); var changes = result.GetTextChanges(cancellationToken); using (Logger.LogBlock(FunctionId.Formatting_ApplyResultToBuffer, cancellationToken)) { document.Project.Solution.Workspace.ApplyTextChanges(document.Id, changes, cancellationToken); } }
public override async Task <Document> RemoveUnnecessaryImportsAsync( Document document, Func <SyntaxNode, bool> predicate, CancellationToken cancellationToken) { predicate ??= Functions <SyntaxNode> .True; using (Logger.LogBlock(FunctionId.Refactoring_RemoveUnnecessaryImports_CSharp, cancellationToken)) { var unnecessaryImports = await GetCommonUnnecessaryImportsOfAllContextAsync( document, predicate, cancellationToken).ConfigureAwait(false); if (unnecessaryImports == null || unnecessaryImports.Any(import => import.OverlapsHiddenPosition(cancellationToken))) { return(document); } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var oldRoot = (CompilationUnitSyntax)root; var newRoot = (CompilationUnitSyntax) new Rewriter(document, unnecessaryImports, cancellationToken).Visit(oldRoot); cancellationToken.ThrowIfCancellationRequested(); #if CODE_STYLE var provider = GetSyntaxFormattingService(); var optionSet = document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(oldRoot.SyntaxTree); var options = SyntaxFormattingOptions.Create(optionSet); #else var provider = document.Project.Solution.Workspace.Services; var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); #endif var spans = new List <TextSpan>(); AddFormattingSpans(newRoot, spans, cancellationToken); var formattedRoot = Formatter.Format(newRoot, spans, provider, options, rules: null, cancellationToken); return(document.WithSyntaxRoot(formattedRoot)); } }
private Solution CreateSolutionWithEventHandler( Document document, string eventHandlerMethodName, int position, out int plusEqualTokenEndPosition, CancellationToken cancellationToken) { _threadingContext.ThrowIfNotOnUIThread(); // Mark the += token with an annotation so we can find it after formatting var plusEqualsTokenAnnotation = new SyntaxAnnotation(); var documentWithNameAndAnnotationsAdded = AddMethodNameAndAnnotationsToSolution(document, eventHandlerMethodName, position, plusEqualsTokenAnnotation, cancellationToken); var semanticDocument = SemanticDocument.CreateAsync(documentWithNameAndAnnotationsAdded, cancellationToken).WaitAndGetResult(cancellationToken); var preferences = CSharpCodeGenerationPreferences.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); var updatedRoot = AddGeneratedHandlerMethodToSolution(semanticDocument, preferences, eventHandlerMethodName, plusEqualsTokenAnnotation, cancellationToken); if (updatedRoot == null) { plusEqualTokenEndPosition = 0; return(null); } var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken); var simplifiedDocument = Simplifier.ReduceAsync(documentWithNameAndAnnotationsAdded.WithSyntaxRoot(updatedRoot), Simplifier.Annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken); var formattedDocument = Formatter.FormatAsync(simplifiedDocument, Formatter.Annotation, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken); var newRoot = formattedDocument.GetSyntaxRootSynchronously(cancellationToken); plusEqualTokenEndPosition = newRoot.GetAnnotatedNodesAndTokens(plusEqualsTokenAnnotation) .Single().Span.End; return(document.Project.Solution.WithDocumentText( formattedDocument.Id, formattedDocument.GetTextSynchronously(cancellationToken))); }
private async Task <ImmutableArray <CodeFix> > GetSuppressionsAsync( Document documentOpt, Project project, IEnumerable <Diagnostic> diagnostics, SuppressionTargetInfo suppressionTargetInfo, bool skipSuppressMessage, bool skipUnsuppress, CancellationToken cancellationToken) { // We only care about diagnostics that can be suppressed/unsuppressed. diagnostics = diagnostics.Where(IsFixableDiagnostic); if (diagnostics.IsEmpty()) { return(ImmutableArray <CodeFix> .Empty); } INamedTypeSymbol suppressMessageAttribute = null; if (!skipSuppressMessage) { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); suppressMessageAttribute = compilation.SuppressMessageAttributeType(); skipSuppressMessage = suppressMessageAttribute == null || !suppressMessageAttribute.IsAttribute(); } var lazyFormattingOptions = (SyntaxFormattingOptions)null; var result = ArrayBuilder <CodeFix> .GetInstance(); foreach (var diagnostic in diagnostics) { if (!diagnostic.IsSuppressed) { var nestedActions = ArrayBuilder <NestedSuppressionCodeAction> .GetInstance(); if (diagnostic.Location.IsInSource && documentOpt != null) { // pragma warning disable. lazyFormattingOptions ??= await SyntaxFormattingOptions.FromDocumentAsync(documentOpt, cancellationToken).ConfigureAwait(false); nestedActions.Add(PragmaWarningCodeAction.Create(suppressionTargetInfo, documentOpt, lazyFormattingOptions, diagnostic, this)); } // SuppressMessageAttribute suppression is not supported for compiler diagnostics. if (!skipSuppressMessage && SuppressionHelpers.CanBeSuppressedWithAttribute(diagnostic)) { // global assembly-level suppress message attribute. nestedActions.Add(new GlobalSuppressMessageCodeAction( suppressionTargetInfo.TargetSymbol, suppressMessageAttribute, project, diagnostic, this)); // local suppress message attribute // please note that in order to avoid issues with existing unit tests referencing the code fix // by their index this needs to be the last added to nestedActions if (suppressionTargetInfo.TargetMemberNode != null && suppressionTargetInfo.TargetSymbol.Kind != SymbolKind.Namespace) { nestedActions.Add(new LocalSuppressMessageCodeAction( this, suppressionTargetInfo.TargetSymbol, suppressMessageAttribute, suppressionTargetInfo.TargetMemberNode, documentOpt, diagnostic)); } } if (nestedActions.Count > 0) { var codeAction = new TopLevelSuppressionCodeAction( diagnostic, nestedActions.ToImmutableAndFree()); result.Add(new CodeFix(project, codeAction, diagnostic)); } } else if (!skipUnsuppress) { var codeAction = await RemoveSuppressionCodeAction.CreateAsync(suppressionTargetInfo, documentOpt, project, diagnostic, this, cancellationToken).ConfigureAwait(false); if (codeAction != null) { result.Add(new CodeFix(project, codeAction, diagnostic)); } } } return(result.ToImmutableAndFree()); }
public override async Task <CompletionChange> GetChangeAsync( Document document, CompletionItem completionItem, char?commitKey, CancellationToken cancellationToken) { var containingNamespace = ImportCompletionItem.GetContainingNamespace(completionItem); var provideParenthesisCompletion = await ShouldProvideParenthesisCompletionAsync( document, completionItem, commitKey, cancellationToken).ConfigureAwait(false); var insertText = completionItem.DisplayText; if (provideParenthesisCompletion) { insertText += "()"; CompletionProvidersLogger.LogCustomizedCommitToAddParenthesis(commitKey); } if (await ShouldCompleteWithFullyQualifyTypeName().ConfigureAwait(false)) { var completionText = $"{containingNamespace}.{insertText}"; return(CompletionChange.Create(new TextChange(completionItem.Span, completionText))); } // Find context node so we can use it to decide where to insert using/imports. var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var addImportContextNode = root.FindToken(completionItem.Span.Start, findInsideTrivia: true).Parent; // Add required using/imports directive. var addImportService = document.GetRequiredLanguageService <IAddImportsService>(); var generator = document.GetRequiredLanguageService <SyntaxGenerator>(); var addImportsOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var importNode = CreateImport(document, containingNamespace); var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); var rootWithImport = addImportService.AddImport(compilation, root, addImportContextNode !, importNode, generator, addImportsOptions, cancellationToken); var documentWithImport = document.WithSyntaxRoot(rootWithImport); // This only formats the annotated import we just added, not the entire document. var formattedDocumentWithImport = await Formatter.FormatAsync(documentWithImport, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false); using var _ = ArrayBuilder <TextChange> .GetInstance(out var builder); // Get text change for add import var importChanges = await formattedDocumentWithImport.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false); builder.AddRange(importChanges); // Create text change for complete type name. // // Note: Don't try to obtain TextChange for completed type name by replacing the text directly, // then use Document.GetTextChangesAsync on document created from the changed text. This is // because it will do a diff and return TextChanges with minimum span instead of actual // replacement span. // // For example: If I'm typing "asd", the completion provider could be triggered after "a" // is typed. Then if I selected type "AsnEncodedData" to commit, by using the approach described // above, we will get a TextChange of "AsnEncodedDat" with 0 length span, instead of a change of // the full display text with a span of length 1. This will later mess up span-tracking and end up // with "AsnEncodedDatasd" in the code. builder.Add(new TextChange(completionItem.Span, insertText)); // Then get the combined change var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var newText = text.WithChanges(builder); var changes = builder.ToImmutable(); var change = Utilities.Collapse(newText, changes); return(CompletionChange.Create(change, changes)); async Task <bool> ShouldCompleteWithFullyQualifyTypeName() { if (!IsAddingImportsSupported(document)) { return(true); } // We might need to qualify unimported types to use them in an import directive, because they only affect members of the containing // import container (e.g. namespace/class/etc. declarations). // // For example, `List` and `StringBuilder` both need to be fully qualified below: // // using CollectionOfStringBuilders = System.Collections.Generic.List<System.Text.StringBuilder>; // // However, if we are typing in an C# using directive that is inside a nested import container (i.e. inside a namespace declaration block), // then we can add an using in the outer import container instead (this is not allowed in VB). // // For example: // // using System.Collections.Generic; // using System.Text; // // namespace Foo // { // using CollectionOfStringBuilders = List<StringBuilder>; // } // // Here we will always choose to qualify the unimported type, just to be consistent and keeps things simple. return(await IsInImportsDirectiveAsync(document, completionItem.Span.Start, cancellationToken).ConfigureAwait(false)); } }
public static async Task <(Document containingDocument, SyntaxAnnotation typeAnnotation)> AddTypeToNewFileAsync( Solution solution, string containingNamespaceDisplay, string fileName, ProjectId projectId, IEnumerable <string> folders, INamedTypeSymbol newSymbol, Document hintDocument, CancellationToken cancellationToken) { var newDocumentId = DocumentId.CreateNewId(projectId, debugName: fileName); var newDocumentPath = PathUtilities.CombinePaths(PathUtilities.GetDirectoryName(hintDocument.FilePath), fileName); var solutionWithInterfaceDocument = solution.AddDocument(newDocumentId, fileName, text: "", folders: folders, filePath: newDocumentPath); var newDocument = solutionWithInterfaceDocument.GetRequiredDocument(newDocumentId); var newSemanticModel = await newDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var context = new CodeGenerationContext( contextLocation: newSemanticModel.SyntaxTree.GetLocation(new TextSpan()), generateMethodBodies: true); // need to remove the root namespace from the containing namespace display because it is implied // For C# this does nothing as there is no root namespace (root namespace is empty string) var generateTypeService = newDocument.GetRequiredLanguageService <IGenerateTypeService>(); var rootNamespace = generateTypeService.GetRootNamespace(newDocument.Project.CompilationOptions); var index = rootNamespace.IsEmpty() ? -1 : containingNamespaceDisplay.IndexOf(rootNamespace); // if we did find the root namespace as the first element, then we remove it // this may leave us with an extra "." character at the start, but when we split it shouldn't matter var namespaceWithoutRoot = index == 0 ? containingNamespaceDisplay.Remove(index, rootNamespace.Length) : containingNamespaceDisplay; var namespaceParts = namespaceWithoutRoot.Split('.').Where(s => !string.IsNullOrEmpty(s)); var newTypeDocument = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync( newDocument.Project.Solution, newSemanticModel.GetEnclosingNamespace(0, cancellationToken), newSymbol.GenerateRootNamespaceOrType(namespaceParts.ToArray()), context, cancellationToken).ConfigureAwait(false); var newTypeFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(newTypeDocument, cancellationToken).ConfigureAwait(false); var formattingService = newTypeDocument.GetLanguageService <INewDocumentFormattingService>(); if (formattingService is not null) { newTypeDocument = await formattingService.FormatNewDocumentAsync(newTypeDocument, hintDocument, newTypeFormattingOptions, cancellationToken).ConfigureAwait(false); } var syntaxRoot = await newTypeDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var typeAnnotation = new SyntaxAnnotation(); var syntaxFacts = newTypeDocument.GetRequiredLanguageService <ISyntaxFactsService>(); var declarationNode = syntaxRoot.DescendantNodes().First(syntaxFacts.IsTypeDeclaration); var annotatedRoot = syntaxRoot.ReplaceNode(declarationNode, declarationNode.WithAdditionalAnnotations(typeAnnotation)); newTypeDocument = newTypeDocument.WithSyntaxRoot(annotatedRoot); var simplified = await Simplifier.ReduceAsync(newTypeDocument, cancellationToken : cancellationToken).ConfigureAwait(false); var formattedDocument = await Formatter.FormatAsync(simplified, newTypeFormattingOptions, cancellationToken).ConfigureAwait(false); return(formattedDocument, typeAnnotation); }
public async Task <ExtractClassOptions?> GetExtractClassOptionsAsync(Document document, INamedTypeSymbol selectedType, ISymbol?selectedMember, CancellationToken cancellationToken) { var notificationService = document.Project.Solution.Workspace.Services.GetRequiredService <INotificationService>(); var membersInType = selectedType.GetMembers(). WhereAsArray(member => MemberAndDestinationValidator.IsMemberValid(member)); var memberViewModels = membersInType .SelectAsArray(member => new PullMemberUpSymbolViewModel(member, _glyphService) { // The member user selected will be checked at the beginning. IsChecked = SymbolEquivalenceComparer.Instance.Equals(selectedMember, member), MakeAbstract = false, IsMakeAbstractCheckable = !member.IsKind(SymbolKind.Field) && !member.IsAbstract, IsCheckable = true }); var memberToDependentsMap = SymbolDependentsBuilder.FindMemberToDependentsMap(membersInType, document.Project, cancellationToken); var conflictingTypeNames = selectedType.ContainingNamespace.GetAllTypes(cancellationToken).Select(t => t.Name); var candidateName = selectedType.Name + "Base"; var defaultTypeName = NameGenerator.GenerateUniqueName(candidateName, name => !conflictingTypeNames.Contains(name)); var containingNamespaceDisplay = selectedType.ContainingNamespace.IsGlobalNamespace ? string.Empty : selectedType.ContainingNamespace.ToDisplayString(); var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false); var generatedNameTypeParameterSuffix = ExtractTypeHelpers.GetTypeParameterSuffix(document, formattingOptions, selectedType, membersInType, cancellationToken); var viewModel = new ExtractClassViewModel( _uiThreadOperationExecutor, notificationService, memberViewModels, memberToDependentsMap, defaultTypeName, containingNamespaceDisplay, document.Project.Language, generatedNameTypeParameterSuffix, conflictingTypeNames.ToImmutableArray(), document.GetRequiredLanguageService <ISyntaxFactsService>()); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var dialog = new ExtractClassDialog(viewModel); var result = dialog.ShowModal(); if (result.GetValueOrDefault()) { return(new ExtractClassOptions( viewModel.DestinationViewModel.FileName, viewModel.DestinationViewModel.TypeName, viewModel.DestinationViewModel.Destination == CommonControls.NewTypeDestination.CurrentFile, viewModel.MemberSelectionViewModel.CheckedMembers.SelectAsArray(m => new ExtractClassMemberAnalysisResult(m.Symbol, m.MakeAbstract)))); } return(null); }