private static async Task <Document> BatchPragmaFixesAsync( AbstractSuppressionCodeFixProvider suppressionFixProvider, Document document, ImmutableArray <IPragmaBasedCodeAction> pragmaActions, ImmutableArray <Diagnostic> diagnostics, CancellationToken cancellationToken) { // We apply all the pragma suppression fixes sequentially. // At every application, we track the updated locations for remaining diagnostics in the document. var currentDiagnosticSpans = new Dictionary <Diagnostic, TextSpan>(); foreach (var diagnostic in diagnostics) { currentDiagnosticSpans.Add(diagnostic, diagnostic.Location.SourceSpan); } var currentDocument = document; for (int i = 0; i < pragmaActions.Length; i++) { var originalpragmaAction = pragmaActions[i]; var diagnostic = diagnostics[i]; // Get the diagnostic span for the diagnostic in latest document snapshot. TextSpan currentDiagnosticSpan; if (!currentDiagnosticSpans.TryGetValue(diagnostic, out currentDiagnosticSpan)) { // Diagnostic whose location conflicts with a prior fix. continue; } // Compute and apply pragma suppression fix. var currentTree = await currentDocument.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var currentLocation = Location.Create(currentTree, currentDiagnosticSpan); diagnostic = Diagnostic.Create( id: diagnostic.Id, category: diagnostic.Descriptor.Category, message: diagnostic.GetMessage(), severity: diagnostic.Severity, defaultSeverity: diagnostic.DefaultSeverity, isEnabledByDefault: diagnostic.Descriptor.IsEnabledByDefault, warningLevel: diagnostic.WarningLevel, title: diagnostic.Descriptor.Title, description: diagnostic.Descriptor.Description, helpLink: diagnostic.Descriptor.HelpLinkUri, location: currentLocation, additionalLocations: diagnostic.AdditionalLocations, customTags: diagnostic.Descriptor.CustomTags, properties: diagnostic.Properties, isSuppressed: diagnostic.IsSuppressed); var newSuppressionFixes = await suppressionFixProvider.GetSuppressionsAsync(currentDocument, currentDiagnosticSpan, SpecializedCollections.SingletonEnumerable(diagnostic), cancellationToken).ConfigureAwait(false); var newSuppressionFix = newSuppressionFixes.SingleOrDefault(); if (newSuppressionFix != null) { var newPragmaAction = newSuppressionFix.Action as IPragmaBasedCodeAction ?? newSuppressionFix.Action.GetCodeActions().OfType <IPragmaBasedCodeAction>().SingleOrDefault(); if (newPragmaAction != null) { // Get the changed document with pragma suppression add/removals. // Note: We do it one token at a time to ensure we get single text change in the new document, otherwise UpdateDiagnosticSpans won't function as expected. // Update the diagnostics spans based on the text changes. var startTokenChanges = await GetChangedDocumentAsync(newPragmaAction, currentDocument, diagnostics, currentDiagnosticSpans, includeStartTokenChange : true, includeEndTokenChange : false, cancellationToken : cancellationToken).ConfigureAwait(false); var endTokenChanges = await GetChangedDocumentAsync(newPragmaAction, currentDocument, diagnostics, currentDiagnosticSpans, includeStartTokenChange : false, includeEndTokenChange : true, cancellationToken : cancellationToken).ConfigureAwait(false); var currentText = await currentDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); var orderedChanges = startTokenChanges.Concat(endTokenChanges).OrderBy(change => change.Span).Distinct(); var newText = currentText.WithChanges(orderedChanges); currentDocument = currentDocument.WithText(newText); } } } return(currentDocument); }
protected override async Task <SyntaxNode> RewriteFieldNameAndAccessibilityAsync(string originalFieldName, bool makePrivate, Document document, SyntaxAnnotation declarationAnnotation, CodeAndImportGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(declarationAnnotation).FirstOrDefault(); // There may be no field to rewrite if this document is part of a set of linked files // and the declaration is not conditionally compiled in this document's project. if (declarator == null) { return(root); } var tempAnnotation = new SyntaxAnnotation(); var escapedName = originalFieldName.EscapeIdentifier(); var newIdentifier = SyntaxFactory.Identifier( leading: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker), contextualKind: SyntaxKind.IdentifierName, text: escapedName, valueText: originalFieldName, trailing: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker)) .WithTrailingTrivia(declarator.Identifier.TrailingTrivia) .WithLeadingTrivia(declarator.Identifier.LeadingTrivia); var updatedDeclarator = declarator.WithIdentifier(newIdentifier).WithAdditionalAnnotations(tempAnnotation); root = root.ReplaceNode(declarator, updatedDeclarator); document = document.WithSyntaxRoot(root); var declaration = root.GetAnnotatedNodes <SyntaxNode>(tempAnnotation).First().Parent as VariableDeclarationSyntax; if (declaration.Variables.Count == 1) { var fieldSyntax = declaration.Parent as FieldDeclarationSyntax; var modifierKinds = new[] { SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword, SyntaxKind.PublicKeyword }; if (makePrivate) { var modifiers = SpecializedCollections.SingletonEnumerable(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)) .Concat(fieldSyntax.Modifiers.Where(m => !modifierKinds.Contains(m.Kind()))); root = root.ReplaceNode(fieldSyntax, fieldSyntax.WithModifiers( SyntaxFactory.TokenList(modifiers)) .WithAdditionalAnnotations(Formatter.Annotation) .WithLeadingTrivia(fieldSyntax.GetLeadingTrivia()) .WithTrailingTrivia(fieldSyntax.GetTrailingTrivia())); } } else if (declaration.Variables.Count > 1 && makePrivate) { document = document.WithSyntaxRoot(root); var codeGenService = document.GetLanguageService <ICodeGenerationService>(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First(); declaration = declarator.Parent as VariableDeclarationSyntax; var field = semanticModel.GetDeclaredSymbol(declarator, cancellationToken) as IFieldSymbol; var fieldToAdd = declarationAnnotation.AddAnnotationToSymbol(CodeGenerationSymbolFactory.CreateFieldSymbol( field.GetAttributes(), Accessibility.Private, new DeclarationModifiers(isStatic: field.IsStatic, isReadOnly: field.IsReadOnly, isConst: field.IsConst), field.Type, field.Name, field.HasConstantValue, field.ConstantValue, declarator.Initializer)); var withField = await codeGenService.AddFieldAsync( new CodeGenerationSolutionContext( document.Project.Solution, CodeGenerationContext.Default, fallbackOptions), field.ContainingType, fieldToAdd, cancellationToken).ConfigureAwait(false); root = await withField.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First(); declaration = declarator.Parent as VariableDeclarationSyntax; return(root.RemoveNode(declarator, SyntaxRemoveOptions.KeepNoTrivia)); } return(root); }
private IEnumerable <INamedTypeSymbol> ResolveErrorTypesWorker(Compilation compilation, bool ignoreAssemblyKey) { return(_containerKey == null ? SpecializedCollections.EmptyEnumerable <INamedTypeSymbol>() : ResolveErrorTypeWithContainer(compilation, ignoreAssemblyKey)); }
internal void ApplyConflictResolutionEdits(IInlineRenameReplacementInfo conflictResolution, LinkedFileMergeSessionResult mergeResult, IEnumerable <Document> documents, CancellationToken cancellationToken) { AssertIsForeground(); if (!AreAllReferenceSpansMappable()) { // don't dynamically update the reference spans for documents with unmappable projections return; } using (new SelectionTracking(this)) { // 1. Undo any previous edits and update the buffer to resulting document after conflict resolution _session.UndoManager.UndoTemporaryEdits(_subjectBuffer, disconnect: false); var newDocument = mergeResult.MergedSolution.GetDocument(documents.First().Id); var originalDocument = _baseDocuments.Single(d => d.Id == newDocument.Id); var changes = GetTextChangesFromTextDifferencingServiceAsync(originalDocument, newDocument, cancellationToken).WaitAndGetResult(cancellationToken); // TODO: why does the following line hang when uncommented? // newDocument.GetTextChangesAsync(this.baseDocuments.Single(d => d.Id == newDocument.Id), cancellationToken).WaitAndGetResult(cancellationToken).Reverse(); _session.UndoManager.CreateConflictResolutionUndoTransaction(_subjectBuffer, () => { using (var edit = _subjectBuffer.CreateEdit(EditOptions.DefaultMinimalChange, null, s_propagateSpansEditTag)) { foreach (var change in changes) { edit.Replace(change.Span.Start, change.Span.Length, change.NewText); } edit.ApplyAndLogExceptions(); } }); // 2. We want to update referenceSpanToLinkedRenameSpanMap where spans were affected by conflict resolution. // We also need to add the remaining document edits to conflictResolutionRenameTrackingSpans // so they get classified/tagged correctly in the editor. _conflictResolutionRenameTrackingSpans.Clear(); var documentReplacements = documents .Select(document => (document, conflictResolution.GetReplacements(document.Id).Where(r => GetRenameSpanKind(r.Kind) != RenameSpanKind.None).ToImmutableArray())) .ToImmutableArray(); var firstDocumentReplacements = documentReplacements.FirstOrDefault(d => !d.Item2.IsEmpty); var bufferContainsLinkedDocuments = documentReplacements.Length > 1 && firstDocumentReplacements.document != null; var linkedDocumentsMightConflict = bufferContainsLinkedDocuments; if (linkedDocumentsMightConflict) { // When changes are made and linked documents are involved, some of the linked documents may // have changes that differ from others. When these changes conflict (both differ and overlap), // the inline rename UI reveals the conflicts. However, the merge process for finding these // conflicts is slow, so we want to avoid it when possible. This code block attempts to set // linkedDocumentsMightConflict back to false, eliminating the need to merge the changes as part // of the conflict detection process. Currently we only special case one scenario: ignoring // documents that have no changes at all, we check if all linked documents have exactly the same // set of changes. // 1. Check if all documents have the same replacement spans (or no replacements) var spansMatch = true; foreach (var(document, replacements) in documentReplacements) { if (document == firstDocumentReplacements.document || replacements.IsEmpty) { continue; } if (replacements.Length != firstDocumentReplacements.Item2.Length) { spansMatch = false; break; } for (var i = 0; i < replacements.Length; i++) { if (!replacements[i].Equals(firstDocumentReplacements.Item2[i])) { spansMatch = false; break; } } if (!spansMatch) { break; } } // 2. If spans match, check content if (spansMatch) { linkedDocumentsMightConflict = false; // Only need to check the new span's content var firstDocumentNewText = conflictResolution.NewSolution.GetDocument(firstDocumentReplacements.document.Id).GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken); var firstDocumentNewSpanText = firstDocumentReplacements.Item2.SelectAsArray(replacement => firstDocumentNewText.ToString(replacement.NewSpan)); foreach (var(document, replacements) in documentReplacements) { if (document == firstDocumentReplacements.document || replacements.IsEmpty) { continue; } var documentNewText = conflictResolution.NewSolution.GetDocument(document.Id).GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken); for (var i = 0; i < replacements.Length; i++) { if (documentNewText.ToString(replacements[i].NewSpan) != firstDocumentNewSpanText[i]) { // Have to use the slower merge process linkedDocumentsMightConflict = true; break; } } if (linkedDocumentsMightConflict) { break; } } } } foreach (var document in documents) { var relevantReplacements = conflictResolution.GetReplacements(document.Id).Where(r => GetRenameSpanKind(r.Kind) != RenameSpanKind.None); if (!relevantReplacements.Any()) { continue; } var mergedReplacements = linkedDocumentsMightConflict ? GetMergedReplacementInfos( relevantReplacements, conflictResolution.NewSolution.GetDocument(document.Id), mergeResult.MergedSolution.GetDocument(document.Id), cancellationToken) : relevantReplacements; // Show merge conflicts comments as unresolvable conflicts, and do not // show any other rename-related spans that overlap a merge conflict comment. var mergeConflictComments = mergeResult.MergeConflictCommentSpans.ContainsKey(document.Id) ? mergeResult.MergeConflictCommentSpans[document.Id] : SpecializedCollections.EmptyEnumerable <TextSpan>(); foreach (var conflict in mergeConflictComments) { // TODO: Add these to the unresolvable conflict counts in the dashboard _conflictResolutionRenameTrackingSpans.Add(new RenameTrackingSpan( _subjectBuffer.CurrentSnapshot.CreateTrackingSpan(conflict.ToSpan(), SpanTrackingMode.EdgeInclusive, TrackingFidelityMode.Forward), RenameSpanKind.UnresolvedConflict)); } foreach (var replacement in mergedReplacements) { var kind = GetRenameSpanKind(replacement.Kind); if (_referenceSpanToLinkedRenameSpanMap.ContainsKey(replacement.OriginalSpan) && kind != RenameSpanKind.Complexified) { var linkedRenameSpan = _session._renameInfo.GetConflictEditSpan( new InlineRenameLocation(newDocument, replacement.NewSpan), _session.ReplacementText, cancellationToken); if (linkedRenameSpan.HasValue) { if (!mergeConflictComments.Any(s => replacement.NewSpan.IntersectsWith(s))) { _referenceSpanToLinkedRenameSpanMap[replacement.OriginalSpan] = new RenameTrackingSpan( _subjectBuffer.CurrentSnapshot.CreateTrackingSpan( linkedRenameSpan.Value.ToSpan(), SpanTrackingMode.EdgeInclusive, TrackingFidelityMode.Forward), kind); } } else { // We might not have a renameable span if an alias conflict completely changed the text _referenceSpanToLinkedRenameSpanMap[replacement.OriginalSpan] = new RenameTrackingSpan( _referenceSpanToLinkedRenameSpanMap[replacement.OriginalSpan].TrackingSpan, RenameSpanKind.None); if (_activeSpan.HasValue && _activeSpan.Value.IntersectsWith(replacement.OriginalSpan)) { _activeSpan = null; } } } else { if (!mergeConflictComments.Any(s => replacement.NewSpan.IntersectsWith(s))) { _conflictResolutionRenameTrackingSpans.Add(new RenameTrackingSpan( _subjectBuffer.CurrentSnapshot.CreateTrackingSpan(replacement.NewSpan.ToSpan(), SpanTrackingMode.EdgeInclusive, TrackingFidelityMode.Forward), kind)); } } } if (!linkedDocumentsMightConflict) { break; } } UpdateReadOnlyRegions(); // 3. Reset the undo state and notify the taggers. this.ApplyReplacementText(updateSelection: false); RaiseSpansChanged(); } }
/// <summary> /// OBSOLETE: Use VerifyDiagnostics from Roslyn.Compilers.CSharp.Test.Utilities instead. /// </summary> public static void VerifyErrorCodes(IEnumerable <Diagnostic> actualErrors, params ErrorDescription[] expectedErrorDesp) { if (expectedErrorDesp == null) { return; } int expectedLength = expectedErrorDesp.Length; int actualLength = actualErrors.Count(); Assert.True( expectedLength == actualLength, String.Format( "ErrCount {0} != {1}{2}Actual errors are:{2}{3}", expectedLength, actualLength, Environment.NewLine, actualLength == 0 ? "<none>" : string.Join(Environment.NewLine, actualErrors))); var actualSortedDesp = (from ae in (from e in actualErrors let lineSpan = e.Location.GetMappedLineSpan() select new ErrorDescription { Code = e.Code, Line = lineSpan.IsValid ? lineSpan.StartLinePosition.Line + 1 : 0, Column = lineSpan.IsValid ? lineSpan.StartLinePosition.Character + 1 : 0, IsWarning = e.Severity == DiagnosticSeverity.Warning, Parameters = (e.Arguments != null && e.Arguments.Count > 0 && e.Arguments[0] != null) ? e.Arguments.Select(x => x != null ? x.ToString() : null).ToArray() : SpecializedCollections.EmptyArray <string>() }) orderby ae.Code, ae.Line, ae.Column select ae).ToList(); var expectedSortedDesp = (from ee in expectedErrorDesp orderby ee.Code, ee.Line, ee.Column select ee).ToList(); int idx = 0; // actual >= expected foreach (var experr in expectedSortedDesp) { while (idx < actualSortedDesp.Count && actualSortedDesp[idx].Code < experr.Code) { idx++; } if (idx >= actualSortedDesp.Count) { idx = actualSortedDesp.Count - 1; } var acterr = actualSortedDesp[idx]; Assert.Equal(experr.Code, acterr.Code); if (experr.Line > 0 && experr.Column > 0) { Assert.True(experr.Line == acterr.Line, String.Format("Line {0}!={1}", experr.Line, acterr.Line)); Assert.True(experr.Column == acterr.Column, String.Format("Col {0}!={1}", experr.Column, acterr.Column)); } Assert.Equal(experr.IsWarning, acterr.IsWarning); //if the expected contains parameters, validate those too. if (experr.Parameters != null) { Assert.True(experr.Parameters.SequenceEqual(acterr.Parameters), String.Format("Param: {0}!={1}", experr.Parameters.Count(), acterr.Parameters.Count())); } idx++; } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var document = context.Document; var span = context.Span; var diagnostics = context.Diagnostics; var cancellationToken = context.CancellationToken; var project = document.Project; var diagnostic = diagnostics.First(); var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(context.CancellationToken)) { return; } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindToken(span.Start).GetAncestors <SyntaxNode>().First(n => n.Span.Contains(span)); // Has to be a simple identifier or generic name. if (node != null && CanFullyQualify(diagnostic, ref node)) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var matchingTypes = await this.GetMatchingTypesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false); var matchingNamespaces = await this.GetMatchingNamespacesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false); if (matchingTypes != null || matchingNamespaces != null) { matchingTypes = matchingTypes ?? SpecializedCollections.EmptyEnumerable <ISymbol>(); matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyEnumerable <ISymbol>(); var matchingTypeContainers = FilterAndSort(GetContainers(matchingTypes, semanticModel.Compilation)); var matchingNamespaceContainers = FilterAndSort(GetContainers(matchingNamespaces, semanticModel.Compilation)); var proposedContainers = matchingTypeContainers.Concat(matchingNamespaceContainers) .Distinct() .Take(8); foreach (var container in proposedContainers) { var containerName = RoslynCompletionData.SafeMinimalDisplayString(container, semanticModel, node.SpanStart); string name; int arity; node.GetNameAndArityOfSimpleName(out name, out arity); // Actual member name might differ by case. string memberName; if (this.IgnoreCase) { var member = container.GetMembers(name).FirstOrDefault(); memberName = member != null ? member.Name : name; } else { memberName = name; } var codeAction = new DocumentChangeAction( node.Span, DiagnosticSeverity.Info, string.Format(GettextCatalog.GetString("Change '{0}' to '{1}.{2}'"), name, containerName, memberName), (c) => { var newRoot = this.ReplaceNode(node, containerName, c); return(Task.FromResult(document.WithSyntaxRoot(newRoot))); }); context.RegisterCodeFix(codeAction, diagnostic); } } } }
private bool ApplySuppressionFix(IEnumerable <DiagnosticData> diagnosticsToFix, Func <Project, bool> shouldFixInProject, bool filterStaleDiagnostics, bool isAddSuppression, bool isSuppressionInSource, bool onlyCompilerDiagnostics, bool showPreviewChangesDialog) { if (diagnosticsToFix == null) { return(false); } diagnosticsToFix = FilterDiagnostics(diagnosticsToFix, isAddSuppression, isSuppressionInSource, onlyCompilerDiagnostics); if (diagnosticsToFix.IsEmpty()) { // Nothing to fix. return(true); } ImmutableDictionary <Document, ImmutableArray <Diagnostic> > documentDiagnosticsToFixMap = null; ImmutableDictionary <Project, ImmutableArray <Diagnostic> > projectDiagnosticsToFixMap = null; var title = GetFixTitle(isAddSuppression); var waitDialogMessage = GetWaitDialogMessage(isAddSuppression); var noDiagnosticsToFix = false; var cancelled = false; var newSolution = _workspace.CurrentSolution; HashSet <string> languages = null; Action <IWaitContext> computeDiagnosticsAndFix = context => { var cancellationToken = context.CancellationToken; cancellationToken.ThrowIfCancellationRequested(); documentDiagnosticsToFixMap = GetDocumentDiagnosticsToFixAsync(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: filterStaleDiagnostics, cancellationToken: cancellationToken) .WaitAndGetResult(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); projectDiagnosticsToFixMap = isSuppressionInSource ? ImmutableDictionary <Project, ImmutableArray <Diagnostic> > .Empty : GetProjectDiagnosticsToFixAsync(diagnosticsToFix, shouldFixInProject, filterStaleDiagnostics: filterStaleDiagnostics, cancellationToken: cancellationToken) .WaitAndGetResult(cancellationToken); if (documentDiagnosticsToFixMap == null || projectDiagnosticsToFixMap == null || (documentDiagnosticsToFixMap.IsEmpty && projectDiagnosticsToFixMap.IsEmpty)) { // Nothing to fix. noDiagnosticsToFix = true; return; } cancellationToken.ThrowIfCancellationRequested(); // Equivalence key determines what fix will be applied. // Make sure we don't include any specific diagnostic ID, as we want all of the given diagnostics (which can have varied ID) to be fixed. var equivalenceKey = isAddSuppression ? (isSuppressionInSource ? FeaturesResources.SuppressWithPragma : FeaturesResources.SuppressWithGlobalSuppressMessage) : FeaturesResources.RemoveSuppressionEquivalenceKeyPrefix; // We have different suppression fixers for every language. // So we need to group diagnostics by the containing project language and apply fixes separately. languages = new HashSet <string>(projectDiagnosticsToFixMap.Keys.Select(p => p.Language).Concat(documentDiagnosticsToFixMap.Select(kvp => kvp.Key.Project.Language))); foreach (var language in languages) { // Use the Fix multiple occurrences service to compute a bulk suppression fix for the specified document and project diagnostics, // show a preview changes dialog and then apply the fix to the workspace. cancellationToken.ThrowIfCancellationRequested(); var documentDiagnosticsPerLanguage = GetDocumentDiagnosticsMappedToNewSolution(documentDiagnosticsToFixMap, newSolution, language); if (!documentDiagnosticsPerLanguage.IsEmpty) { var suppressionFixer = GetSuppressionFixer(documentDiagnosticsPerLanguage.SelectMany(kvp => kvp.Value), language, _codeFixService); if (suppressionFixer != null) { var suppressionFixAllProvider = suppressionFixer.GetFixAllProvider(); newSolution = _fixMultipleOccurencesService.GetFix( documentDiagnosticsPerLanguage, _workspace, suppressionFixer, suppressionFixAllProvider, equivalenceKey, title, waitDialogMessage, cancellationToken); if (newSolution == null) { // User cancelled or fixer threw an exception, so we just bail out. cancelled = true; return; } } } var projectDiagnosticsPerLanguage = GetProjectDiagnosticsMappedToNewSolution(projectDiagnosticsToFixMap, newSolution, language); if (!projectDiagnosticsPerLanguage.IsEmpty) { var suppressionFixer = GetSuppressionFixer(projectDiagnosticsPerLanguage.SelectMany(kvp => kvp.Value), language, _codeFixService); if (suppressionFixer != null) { var suppressionFixAllProvider = suppressionFixer.GetFixAllProvider(); newSolution = _fixMultipleOccurencesService.GetFix( projectDiagnosticsPerLanguage, _workspace, suppressionFixer, suppressionFixAllProvider, equivalenceKey, title, waitDialogMessage, cancellationToken); if (newSolution == null) { // User cancelled or fixer threw an exception, so we just bail out. cancelled = true; return; } } } } }; var result = InvokeWithWaitDialog(computeDiagnosticsAndFix, title, waitDialogMessage); // Bail out if the user cancelled. if (cancelled || result == WaitIndicatorResult.Canceled) { return(false); } else if (noDiagnosticsToFix || newSolution == _workspace.CurrentSolution) { // No changes. return(true); } if (showPreviewChangesDialog) { newSolution = FixAllGetFixesService.PreviewChanges( _workspace.CurrentSolution, newSolution, fixAllPreviewChangesTitle: title, fixAllTopLevelHeader: title, languageOpt: languages?.Count == 1 ? languages.Single() : null, workspace: _workspace); if (newSolution == null) { return(false); } } waitDialogMessage = isAddSuppression ? ServicesVSResources.ApplyingSuppressionFix : ServicesVSResources.ApplyingRemoveSuppressionFix; Action <IWaitContext> applyFix = context => { var operations = SpecializedCollections.SingletonEnumerable <CodeActionOperation>(new ApplyChangesOperation(newSolution)); _editHandlerService.Apply( _workspace, fromDocument: null, operations: operations, title: title, progressTracker: context.ProgressTracker, cancellationToken: context.CancellationToken); }; result = InvokeWithWaitDialog(applyFix, title, waitDialogMessage); if (result == WaitIndicatorResult.Canceled) { return(false); } // Kick off diagnostic re-analysis for affected projects so that diagnostics gets refreshed. Task.Run(() => { var reanalyzeDocuments = diagnosticsToFix.Where(d => d.DocumentId != null).Select(d => d.DocumentId).Distinct(); _diagnosticService.Reanalyze(_workspace, documentIds: reanalyzeDocuments, highPriority: true); }); return(true); }
public IEnumerable <INestedTypeDefinition> GetNestedTypes(EmitContext context) { return(SpecializedCollections.EmptyEnumerable <INestedTypeDefinition>()); }
public IEnumerable <IPropertyDefinition> GetProperties(EmitContext context) { return(SpecializedCollections.EmptyEnumerable <IPropertyDefinition>()); }
private void OnDocumentActiveContextChanged(object sender, DocumentActiveContextChangedEventArgs e) { Reanalyze(e.Solution.Workspace, documentIds: SpecializedCollections.SingletonEnumerable(e.NewActiveContextDocumentId), highPriority: true); }
public static bool SpansPreprocessorDirective(this ISyntaxFactsService service, SyntaxNode node) => service.SpansPreprocessorDirective(SpecializedCollections.SingletonEnumerable(node));
public override IEnumerable <Cci.IFileReference> GetFiles(EmitContext context) => SpecializedCollections.EmptyEnumerable <Cci.IFileReference>();
internal static void VerifyParamArrayAttribute(ParameterSymbol parameter, SourceModuleSymbol module, bool expected = true, OutputKind outputKind = OutputKind.ConsoleApplication) { Assert.Equal(expected, parameter.IsParams); var emitModule = new PEAssemblyBuilder(module.ContainingSourceAssembly, null, outputKind, GetDefaultModulePropertiesForSerialization(), SpecializedCollections.EmptyEnumerable <ResourceDescription>()); var paramArrayAttributeCtor = (MethodSymbol)emitModule.Compilation.GetWellKnownTypeMember(WellKnownMember.System_ParamArrayAttribute__ctor); bool found = false; var context = new Microsoft.CodeAnalysis.Emit.Context(emitModule, null, new DiagnosticBag()); foreach (Microsoft.Cci.ICustomAttribute attr in parameter.GetSynthesizedAttributes()) { if (paramArrayAttributeCtor == (MethodSymbol)attr.Constructor(context)) { Assert.False(found, "Multiple ParamArrayAttribute"); found = true; } } Assert.Equal(expected, found); context.Diagnostics.Verify(); }
internal override IEnumerable <Cci.SecurityAttribute> GetSecurityInformation() { return(SpecializedCollections.EmptyEnumerable <Cci.SecurityAttribute>()); }
private void ProcessUnreachableDiagnostic( SyntaxNodeAnalysisContext context, SyntaxNode root, TextSpan sourceSpan, bool fadeOutCode) { var node = root.FindNode(sourceSpan); // Note: this approach works as the language only supports the concept of // unreachable statements. If we ever get unreachable subexpressions, then // we'll need to revise this code accordingly. var firstUnreachableStatement = node.FirstAncestorOrSelf <StatementSyntax>(); if (firstUnreachableStatement == null || firstUnreachableStatement.SpanStart != sourceSpan.Start) { return; } // At a high level, we can think about us wanting to fade out a "section" of unreachable // statements. However, the compiler only reports the first statement in that "section". // We want to figure out what other statements are in that section and fade them all out // along with the first statement. This is made somewhat tricky due to the fact that // subsequent sibling statements possibly being reachable due to explicit gotos+labels. // // On top of this, an unreachable section might not be contiguous. This is possible // when there is unreachable code that contains a local function declaration in-situ. // This is legal, and the local function declaration may be called from other reachable code. // // As such, it's not possible to just get first unreachable statement, and the last, and // then report that whole region as unreachable. Instead, when we are told about an // unreachable statement, we simply determine which other statements are also unreachable // and bucket them into contiguous chunks. // // We then fade each of these contiguous chunks, while also having each diagnostic we // report point back to the first unreachable statement so that we can easily determine // what to remove if the user fixes the issue. (The fix itself has to go recompute this // as the total set of statements to remove may be larger than the actual faded code // that that diagnostic corresponds to). // Get the location of this first unreachable statement. It will be given to all // the diagnostics we create off of this single compiler diagnostic so that we always // know how to find it regardless of which of our diagnostics the user invokes the // fix off of. var firstStatementLocation = root.SyntaxTree.GetLocation(firstUnreachableStatement.FullSpan); if (!firstUnreachableStatement.IsParentKind(SyntaxKind.Block) && !firstUnreachableStatement.IsParentKind(SyntaxKind.SwitchSection)) { // Can't actually remove this statement (it's an embedded statement in something // like an 'if-statement'). Just fade the code out, but don't offer to remove it. if (fadeOutCode) { context.ReportDiagnostic( Diagnostic.Create(UnnecessaryWithoutSuggestionDescriptor, firstStatementLocation)); } return; } // 'additionalLocations' is how we always pass along the locaiton of the first unreachable // statement in this group. var additionalLocations = SpecializedCollections.SingletonEnumerable(firstStatementLocation); var descriptor = fadeOutCode ? UnnecessaryWithSuggestionDescriptor : HiddenDescriptor; context.ReportDiagnostic( Diagnostic.Create(descriptor, firstStatementLocation, additionalLocations)); var sections = RemoveUnreachableCodeHelpers.GetSubsequentUnreachableSections(firstUnreachableStatement); foreach (var section in sections) { var span = TextSpan.FromBounds(section[0].FullSpan.Start, section.Last().FullSpan.End); var location = root.SyntaxTree.GetLocation(span); // Mark subsequent sections as being 'cascaded'. We don't need to actually process them // when doing a fix-all as they'll be scooped up when we process the fix for the first // section. context.ReportDiagnostic( Diagnostic.Create(descriptor, location, additionalLocations, s_subsequentSectionProperties)); } }
public IEnumerable <ICustomAttribute> GetAttributes(EmitContext context) { return(SpecializedCollections.EmptyEnumerable <ICustomAttribute>()); }
public AnalyzerManager(DiagnosticAnalyzer analyzer) { _analyzerExecutionContextMap = CreateAnalyzerExecutionContextMap(SpecializedCollections.SingletonEnumerable(analyzer)); }
public IEnumerable <IEventDefinition> GetEvents(EmitContext context) { return(SpecializedCollections.EmptyEnumerable <IEventDefinition>()); }
private Tuple <string[], string> GetNamespaceContainersAndAddUsingsOrImport( bool isDialog, IList <string> folders, bool areFoldersValidIdentifiers, Project targetProject, Project triggeringProject) { string includeUsingsOrImports = null; if (!areFoldersValidIdentifiers) { folders = SpecializedCollections.EmptyList <string>(); } // Now actually create the symbol that we want to add to the root namespace. The // symbol may either be a named type (if we're not generating into a namespace) or // it may be a namespace symbol. string[] containers = null; if (!isDialog) { // Not generated from the Dialog containers = GetNamespaceToGenerateInto().Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); } else if (!_service.IsSimpleName(_state.NameOrMemberAccessExpression)) { // If the usage was with a namespace containers = GetNamespaceToGenerateIntoForUsageWithNamespace(targetProject, triggeringProject).Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); } else { // Generated from the Dialog List <string> containerList = new List <string>(); string rootNamespaceOfTheProjectGeneratedInto; if (_targetProjectChangeInLanguage == TargetProjectChangeInLanguage.NoChange) { rootNamespaceOfTheProjectGeneratedInto = _service.GetRootNamespace(_generateTypeOptionsResult.Project.CompilationOptions).Trim(); } else { rootNamespaceOfTheProjectGeneratedInto = _targetLanguageService.GetRootNamespace(_generateTypeOptionsResult.Project.CompilationOptions).Trim(); } var projectManagementService = _document.Project.Solution.Workspace.Services.GetService <IProjectManagementService>(); var defaultNamespace = _generateTypeOptionsResult.DefaultNamespace; // Case 1 : If the type is generated into the same C# project or // Case 2 : If the type is generated from a C# project to a C# Project // Case 3 : If the Type is generated from a VB Project to a C# Project // Using and Namespace will be the DefaultNamespace + Folder Structure if ((_document.Project == _generateTypeOptionsResult.Project && _document.Project.Language == LanguageNames.CSharp) || (_targetProjectChangeInLanguage == TargetProjectChangeInLanguage.NoChange && _generateTypeOptionsResult.Project.Language == LanguageNames.CSharp) || _targetProjectChangeInLanguage == TargetProjectChangeInLanguage.VisualBasicToCSharp) { if (!string.IsNullOrWhiteSpace(defaultNamespace)) { containerList.Add(defaultNamespace); } // Populate the ContainerList AddFoldersToNamespaceContainers(containerList, folders); containers = containerList.ToArray(); includeUsingsOrImports = string.Join(".", containerList.ToArray()); } // Case 4 : If the type is generated into the same VB project or // Case 5 : If Type is generated from a VB Project to VB Project // Case 6 : If Type is generated from a C# Project to VB Project // Namespace will be Folder Structure and Import will have the RootNamespace of the project generated into as part of the Imports if ((_document.Project == _generateTypeOptionsResult.Project && _document.Project.Language == LanguageNames.VisualBasic) || (_document.Project != _generateTypeOptionsResult.Project && _targetProjectChangeInLanguage == TargetProjectChangeInLanguage.NoChange && _generateTypeOptionsResult.Project.Language == LanguageNames.VisualBasic) || _targetProjectChangeInLanguage == TargetProjectChangeInLanguage.CSharpToVisualBasic) { // Populate the ContainerList AddFoldersToNamespaceContainers(containerList, folders); containers = containerList.ToArray(); includeUsingsOrImports = string.Join(".", containerList.ToArray()); if (!string.IsNullOrWhiteSpace(rootNamespaceOfTheProjectGeneratedInto)) { includeUsingsOrImports = string.IsNullOrEmpty(includeUsingsOrImports) ? rootNamespaceOfTheProjectGeneratedInto : rootNamespaceOfTheProjectGeneratedInto + "." + includeUsingsOrImports; } } Contract.Assert(includeUsingsOrImports != null); } return(Tuple.Create(containers, includeUsingsOrImports)); }
public IEnumerable <MethodImplementation> GetExplicitImplementationOverrides(EmitContext context) { return(SpecializedCollections.EmptyEnumerable <MethodImplementation>()); }
IEnumerable <Cci.ICustomAttribute> Cci.IReference.GetAttributes(EmitContext context) => SpecializedCollections.EmptyEnumerable <Cci.ICustomAttribute>();
public IEnumerable <IFieldDefinition> GetFields(EmitContext context) { return(SpecializedCollections.EmptyEnumerable <IFieldDefinition>()); }
private static SyntaxNode CreateNotImplementedException(SyntaxGenerator codeDefinitionFactory, Compilation compilation) => codeDefinitionFactory.ObjectCreationExpression( codeDefinitionFactory.TypeExpression(compilation.NotImplementedExceptionType(), addImport: false), SpecializedCollections.EmptyList <SyntaxNode>());
public IEnumerable <TypeReferenceWithAttributes> Interfaces(EmitContext context) { return(SpecializedCollections.EmptyEnumerable <TypeReferenceWithAttributes>()); }
public override IEnumerable <TextChange> GetTextChanges(TextSpan textSpan) { return(SpecializedCollections.SingletonEnumerable <TextChange>(new TextChange(textSpan, _newString))); }
internal virtual async Task <ImmutableDictionary <Document, ImmutableArray <Diagnostic> > > GetDocumentDiagnosticsToFixAsync( FixAllContext fixAllContext) { using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation_Diagnostics, fixAllContext.CancellationToken)) { var allDiagnostics = ImmutableArray <Diagnostic> .Empty; var projectsToFix = ImmutableArray <Project> .Empty; var document = fixAllContext.Document; var project = fixAllContext.Project; var generatedCodeServices = project.Solution.Workspace.Services.GetService <IGeneratedCodeRecognitionService>(); switch (fixAllContext.Scope) { case FixAllScope.Document: if (document != null && !generatedCodeServices.IsGeneratedCode(document)) { var documentDiagnostics = await fixAllContext.GetDocumentDiagnosticsAsync(document).ConfigureAwait(false); var kvp = SpecializedCollections.SingletonEnumerable(KeyValuePair.Create(document, documentDiagnostics)); return(ImmutableDictionary.CreateRange(kvp)); } break; case FixAllScope.Project: projectsToFix = ImmutableArray.Create(project); allDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(project).ConfigureAwait(false); break; case FixAllScope.Solution: projectsToFix = project.Solution.Projects .Where(p => p.Language == project.Language) .ToImmutableArray(); var diagnostics = new ConcurrentBag <Diagnostic>(); var tasks = new Task[projectsToFix.Length]; for (int i = 0; i < projectsToFix.Length; i++) { fixAllContext.CancellationToken.ThrowIfCancellationRequested(); var projectToFix = projectsToFix[i]; tasks[i] = Task.Run(async() => { var projectDiagnostics = await fixAllContext.GetAllDiagnosticsAsync(projectToFix).ConfigureAwait(false); foreach (var diagnostic in projectDiagnostics) { fixAllContext.CancellationToken.ThrowIfCancellationRequested(); diagnostics.Add(diagnostic); } }, fixAllContext.CancellationToken); } await Task.WhenAll(tasks).ConfigureAwait(false); allDiagnostics = allDiagnostics.AddRange(diagnostics); break; } if (allDiagnostics.IsEmpty) { return(ImmutableDictionary <Document, ImmutableArray <Diagnostic> > .Empty); } return(await GetDocumentDiagnosticsToFixAsync(allDiagnostics, projectsToFix, generatedCodeServices.IsGeneratedCode, fixAllContext.CancellationToken).ConfigureAwait(false)); } }
internal override IEnumerable <FieldSymbol> GetFieldsToEmit() { return(SpecializedCollections.EmptyEnumerable <FieldSymbol>()); }
protected static void AddMappedDocument(Workspace workspace, string markup) { var generatedDocumentId = DocumentId.CreateNewId(workspace.CurrentSolution.ProjectIds.First()); var version = VersionStamp.Create(); var loader = TextLoader.From(TextAndVersion.Create(SourceText.From(markup), version, TestSpanMapper.GeneratedFileName)); var generatedDocumentInfo = DocumentInfo.Create(generatedDocumentId, TestSpanMapper.GeneratedFileName, SpecializedCollections.EmptyReadOnlyList <string>(), SourceCodeKind.Regular, loader, $"C:\\{TestSpanMapper.GeneratedFileName}", isGenerated: true, designTimeOnly: false, new TestSpanMapperProvider()); var newSolution = workspace.CurrentSolution.AddDocument(generatedDocumentInfo); workspace.TryApplyChanges(newSolution); }
private IEnumerable <IFormattingRule> GetFormattingRules(Document document) { return(SpecializedCollections.SingletonEnumerable(BraceCompletionFormattingRule.Instance).Concat(Formatter.GetDefaultFormattingRules(document))); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var document = context.Document; var span = context.Span; var diagnostics = context.Diagnostics; var cancellationToken = context.CancellationToken; var project = document.Project; var diagnostic = diagnostics.First(); var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(context.CancellationToken)) { return; } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (root.FullSpan.Length < span.Start) { return; } var ancestors = root.FindToken(span.Start, findInsideTrivia: true).GetAncestors <SyntaxNode>(); if (!ancestors.Any()) { return; } var node = ancestors.FirstOrDefault(n => n.Span.Contains(span) && n != root); if (node == null) { return; } var placeSystemNamespaceFirst = true; //document.Project.Solution.Workspace.Options.GetOption(Microsoft.CodeAnalysis.Shared.Options.OrganizerOptions.PlaceSystemNamespaceFirst, document.Project.Language); if (!cancellationToken.IsCancellationRequested) { if (this.CanAddImport(node, cancellationToken)) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); //var containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken); //var containingTypeOrAssembly = containingType ?? (ISymbol)semanticModel.Compilation.Assembly; var namespacesInScope = this.GetNamespacesInScope(semanticModel, node, cancellationToken); var matchingTypesNamespaces = await this.GetNamespacesForMatchingTypesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false); var matchingTypes = await this.GetMatchingTypesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false); var matchingNamespaces = await this.GetNamespacesForMatchingNamespacesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false); var matchingExtensionMethodsNamespaces = await this.GetNamespacesForMatchingExtensionMethodsAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false); var matchingFieldsAndPropertiesAsync = await this.GetNamespacesForMatchingFieldsAndPropertiesAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false); var queryPatternsNamespaces = await this.GetNamespacesForQueryPatternsAsync(project, diagnostic, node, semanticModel, namespacesInScope, cancellationToken).ConfigureAwait(false); if (matchingTypesNamespaces != null || matchingNamespaces != null || matchingExtensionMethodsNamespaces != null || matchingFieldsAndPropertiesAsync != null || queryPatternsNamespaces != null || matchingTypes != null) { matchingTypesNamespaces = matchingTypesNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>(); matchingNamespaces = matchingNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>(); matchingExtensionMethodsNamespaces = matchingExtensionMethodsNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>(); matchingFieldsAndPropertiesAsync = matchingFieldsAndPropertiesAsync ?? SpecializedCollections.EmptyList <INamespaceSymbol>(); queryPatternsNamespaces = queryPatternsNamespaces ?? SpecializedCollections.EmptyList <INamespaceSymbol>(); matchingTypes = matchingTypes ?? SpecializedCollections.EmptyList <ITypeSymbol>(); var proposedImports = matchingTypesNamespaces.Cast <INamespaceOrTypeSymbol> () .Concat(matchingNamespaces.Cast <INamespaceOrTypeSymbol> ()) .Concat(matchingExtensionMethodsNamespaces.Cast <INamespaceOrTypeSymbol> ()) .Concat(matchingFieldsAndPropertiesAsync.Cast <INamespaceOrTypeSymbol> ()) .Concat(queryPatternsNamespaces.Cast <INamespaceOrTypeSymbol> ()) .Concat(matchingTypes.Cast <INamespaceOrTypeSymbol> ()) .Distinct() .Where(NotNull) .Where(NotGlobalNamespace) .ToList(); proposedImports.Sort(INamespaceOrTypeSymbolExtensions.CompareNamespaceOrTypeSymbols); proposedImports = proposedImports.Take(8).ToList(); if (proposedImports.Count > 0) { cancellationToken.ThrowIfCancellationRequested(); foreach (var import in proposedImports) { var action = new DocumentChangeAction( node.Span, DiagnosticSeverity.Error, this.GetDescription(import, semanticModel, node), (c) => this.AddImportAsync(node, import, document, placeSystemNamespaceFirst, cancellationToken) ); context.RegisterCodeFix(action, diagnostic); } } } } } }