提交 b42117c3 编写于 作者: S srivatsn

Removing IVT from workspaces to FxCop analyzers

Now that Matt has gone through the fxcop fixers and switched them to use SyntaxGenerator, we can remove IVT from workspaces - i just needed to add a few simple helpers - nothing unreasonable. (changeset 1407864)
上级 8e6daed7
......@@ -75,13 +75,17 @@
<ItemGroup>
<Compile Include="Design\CodeFixes\CA1001CSharpCodeFixProvider.cs" />
<Compile Include="Design\CodeFixes\CA1008CSharpCodeFixProvider.cs" />
<Compile Include="Design\CodeFixes\CA1052CSharpCodeFixProvider.cs" />
<Compile Include="Design\CodeFixes\CA1052CSharpCodeFixProvider.cs" >
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
</Compile>
<Compile Include="Design\CodeFixes\EnumWithFlagsCSharpCodeFixProvider.cs" />
<Compile Include="Design\CSharpCA1003DiagnosticAnalyzer.cs" />
<Compile Include="Design\CSharpCA1019DiagnosticAnalyzer.cs" />
<Compile Include="Design\CSharpCA1024DiagnosticAnalyzer.cs" />
<Compile Include="Design\CSharpEnumWithFlagsDiagnosticAnalyzer.cs" />
<Compile Include="Globalization\CodeFixes\CA1309CSharpCodeFixProvider.cs" />
<Compile Include="Globalization\CodeFixes\CA1309CSharpCodeFixProvider.cs" >
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
</Compile>
<Compile Include="Globalization\CodeFixes\CA2101CSharpCodeFixProvider.cs" />
<Compile Include="Globalization\CSharpCA1309DiagnosticAnalyzer.cs" />
<Compile Include="Performance\CodeFixes\CA1813CSharpCodeFixProvider.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
......@@ -34,22 +36,28 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
cancellationToken.ThrowIfCancellationRequested();
var root = await document.GetSyntaxRootAsync(cancellationToken);
var classDeclaration = root.FindToken(span.Start).GetAncestor<ClassDeclarationSyntax>();
var classDeclaration = root.FindToken(span.Start).Parent?.FirstAncestorOrSelf<ClassDeclarationSyntax>();
if (classDeclaration != null)
{
var staticKeyword = SyntaxFactory.Token(SyntaxKind.StaticKeyword).WithAdditionalAnnotations(Formatter.Annotation);
var newDeclaration = classDeclaration.AddModifiers(staticKeyword);
var newRoot = root.ReplaceNode(classDeclaration, newDeclaration);
context.RegisterCodeFix(
new MyCodeAction(string.Format(FxCopRulesResources.StaticHolderTypeIsNotStatic, classDeclaration.Identifier.Text), document.WithSyntaxRoot(newRoot)),
context.Diagnostics);
var title = string.Format(FxCopRulesResources.StaticHolderTypeIsNotStatic, classDeclaration.Identifier.Text);
var codeAction = new MyCodeAction(title, ct => AddStaticKeyword(document, root, classDeclaration));
context.RegisterCodeFix(codeAction, context.Diagnostics);
}
}
private class MyCodeAction : CodeAction.DocumentChangeAction
private Task<Document> AddStaticKeyword(Document document, SyntaxNode root, ClassDeclarationSyntax classDeclaration)
{
var staticKeyword = SyntaxFactory.Token(SyntaxKind.StaticKeyword).WithAdditionalAnnotations(Formatter.Annotation);
var newDeclaration = classDeclaration.AddModifiers(staticKeyword);
var newRoot = root.ReplaceNode(classDeclaration, newDeclaration);
return Task.FromResult(document.WithSyntaxRoot(newRoot));
}
private class MyCodeAction : DocumentChangeAction
{
public MyCodeAction(string title, Document newDocument) :
base(title, c => Task.FromResult(newDocument))
public MyCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument) :
base(title, createChangedDocument)
{
}
}
......
......@@ -21,7 +21,7 @@ internal override Task<Document> GetUpdatedDocumentAsync(Document document, Sema
// if nothing can be fixed, return the unchanged node
var newRoot = root;
var kind = nodeToFix.Kind();
var syntaxFactoryService = document.GetLanguageService<SyntaxGenerator>();
var syntaxFactoryService = document.Project.LanguageServices.GetService<SyntaxGenerator>();
switch (kind)
{
case SyntaxKind.Argument:
......@@ -44,7 +44,7 @@ internal override Task<Document> GetUpdatedDocumentAsync(Document document, Sema
// string.Equals(a, b) => string.Equals(a, b, StringComparison.Ordinal)
// string.Compare(a, b) => string.Compare(a, b, StringComparison.Ordinal)
var identifier = (IdentifierNameSyntax)nodeToFix;
var invokeParent = identifier.GetAncestor<InvocationExpressionSyntax>();
var invokeParent = identifier.Parent?.FirstAncestorOrSelf<InvocationExpressionSyntax>();
if (invokeParent != null)
{
var methodSymbol = model.GetSymbolInfo(identifier, cancellationToken).Symbol as IMethodSymbol;
......
......@@ -45,7 +45,7 @@ internal override Task<Document> GetUpdatedDocumentAsync(Document document, Sema
return Task.FromResult(document);
}
var factory = document.GetLanguageService<SyntaxGenerator>();
var factory = document.Project.LanguageServices.GetService<SyntaxGenerator>();
var symbol = model.GetDeclaredSymbol(syntaxNode, cancellationToken);
// handle a case where a local in the Dipose method with the same name by generating this (or ClassName) and simplifying it
......
......@@ -39,7 +39,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
}
}
private class MyCodeAction : CodeAction.DocumentChangeAction
private class MyCodeAction : DocumentChangeAction
{
public MyCodeAction(string title, Document newDocument) :
base(title, c => Task.FromResult(newDocument))
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
......
......@@ -3,11 +3,9 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
......
......@@ -5,7 +5,6 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
......
......@@ -6,7 +6,6 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
......
......@@ -2,9 +2,7 @@
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
{
......
......@@ -3,10 +3,12 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
......@@ -39,7 +41,7 @@ protected sealed override string GetCodeFixDescription(Diagnostic diagnostic)
}
}
throw ExceptionUtilities.Unreachable;
throw new InvalidOperationException("This program location is thought to be unreachable.");
}
private static SyntaxNode GetDeclaration(ISymbol symbol)
......@@ -136,7 +138,7 @@ private Document GetUpdatedDocumentWithFix(Document document, SyntaxNode root, S
internal sealed override async Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken)
{
ISymbol declaredSymbol = model.GetDeclaredSymbol(nodeToFix, cancellationToken);
Contract.ThrowIfNull(declaredSymbol);
Debug.Assert(declaredSymbol != null);
var editor = SymbolEditor.Create(document);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
......@@ -42,7 +41,7 @@ internal virtual SyntaxNode GetUpdatedRoot(SyntaxNode root, SyntaxNode nodeToFix
internal sealed override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken)
{
var flagsAttributeType = WellKnownTypes.FlagsAttribute(model.Compilation);
Contract.ThrowIfNull(flagsAttributeType);
Debug.Assert(flagsAttributeType != null);
var workspace = document.Project.Solution.Workspace;
var newEnumBlockSyntax = diagnostic.Id == EnumWithFlagsDiagnosticAnalyzer.RuleIdMarkEnumsWithFlags ?
......@@ -62,7 +61,7 @@ private static SyntaxNode AddFlagsAttribute(Workspace workspace, SyntaxNode enum
private static SyntaxNode RemoveFlagsAttribute(Workspace workspace, SemanticModel model, SyntaxNode enumTypeSyntax, INamedTypeSymbol flagsAttributeType, CancellationToken cancellationToken)
{
var enumType = model.GetDeclaredSymbol(enumTypeSyntax, cancellationToken) as INamedTypeSymbol;
Contract.ThrowIfNull(enumType);
Debug.Assert(enumType != null);
var flagsAttribute = enumType.GetAttributes().First(a => a.AttributeClass == flagsAttributeType);
var attributeNode = flagsAttribute.ApplicationSyntaxReference.GetSyntax(cancellationToken);
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -91,7 +92,7 @@ protected override void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compi
IEnumerable<ulong> missingValues;
if (!ShouldBeFlags(memberValues, out missingValues))
{
Contract.ThrowIfNull(missingValues);
Debug.Assert(missingValues != null);
var missingValuesString = missingValues.Select(v => v.ToString()).Aggregate((i, j) => i + ", " + j);
var location = GetDiagnosticLocation(symbol.DeclaringSyntaxReferences[0].GetSyntax(cancellationToken));
......@@ -116,7 +117,7 @@ protected override void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compi
private static bool IsContiguous(IList<ulong> list)
{
Contract.ThrowIfNull(list);
Debug.Assert(list != null);
bool first = true;
ulong previous = 0;
......@@ -155,7 +156,7 @@ private static bool ShouldBeFlags(IList<ulong> enumValues)
private static ulong GetMissingBitsInBinaryForm(IList<ulong> values)
{
Contract.ThrowIfNull(values);
Debug.Assert(values != null);
// all the powers of two that are individually represented
ulong powersOfTwo = 0;
......
using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics
namespace Microsoft.CodeAnalysis.Diagnostics
{
internal static class DiagnosticCustomTags
{
......@@ -14,20 +11,8 @@ public static string[] Microsoft
{
get
{
Assert(MicrosoftCustomTags, WellKnownDiagnosticTags.Telemetry);
return MicrosoftCustomTags;
}
}
[Conditional("DEBUG")]
private static void Assert(string[] customTags, params string[] tags)
{
Contract.Requires(customTags.Length == tags.Length);
for (int i = 0; i < tags.Length; i++)
{
Contract.Requires(customTags[i] == tags[i]);
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
namespace Microsoft.CodeAnalysis
{
internal class DocumentChangeAction : CodeAction
{
private readonly string title;
private readonly Func<CancellationToken, Task<Document>> createChangedDocument;
public DocumentChangeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument)
{
this.title = title;
this.createChangedDocument = createChangedDocument;
}
public override string Title
{
get { return this.title; }
}
protected override Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
{
return this.createChangedDocument(cancellationToken);
}
}
}
\ No newline at end of file
......@@ -119,6 +119,7 @@
<Compile Include="Design\EnumWithFlagsDiagnosticAnalyzer.cs" />
<Compile Include="Design\StaticTypeRulesDiagnosticAnalyzer.cs" />
<Compile Include="DiagnosticKind.cs" />
<Compile Include="DocumentChangeAction.cs" />
<Compile Include="FxCopDiagnosticCategory.cs" />
<Compile Include="FxCopFixersResources.Designer.cs">
<AutoGen>True</AutoGen>
......@@ -147,14 +148,18 @@
<Compile Include="Shared\CommonAccessibilityUtilities.cs" />
<Compile Include="Shared\DiagnosticHelpers.cs" />
<Compile Include="Shared\Extensions\DiagnosticExtensions.cs" />
<Compile Include="Shared\Extensions\IEnumerableExtensions.cs" />
<Compile Include="Shared\Extensions\INamedTypeSymbolExtensions.cs" />
<Compile Include="Shared\Extensions\ISymbolExtensions.cs" />
<Compile Include="Shared\Extensions\ISymbolExtensions.cs">
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
</Compile>
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.cs" />
<Compile Include="Shared\Extensions\ObjectExtensions.cs" />
<Compile Include="Shared\WellKnownTypes.cs" />
<Compile Include="Shared\WordParser.cs" />
<Compile Include="Shared\WordParserOptions.cs" />
<Compile Include="Design\CA1036DiagnosticAnalyzer.cs" />
<Compile Include="SolutionChangeAction.cs" />
<Compile Include="Usage\CA2200DiagnosticAnalyzer.cs" />
<Compile Include="Usage\CA2213DiagnosticAnalyzer.cs" />
<Compile Include="Usage\CA2214DiagnosticAnalyzer.cs" />
......@@ -193,4 +198,4 @@
<Import Project="..\..\..\..\packages\StyleCop.MSBuild.4.7.48.2\build\StyleCop.MSBuild.Targets" Condition="Exists('..\..\..\..\packages\StyleCop.MSBuild.4.7.48.2\build\StyleCop.MSBuild.Targets')" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
......@@ -2,7 +2,6 @@
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
......
......@@ -4,7 +4,6 @@
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Globalization
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
......
......@@ -6,10 +6,8 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Naming
......@@ -249,7 +247,7 @@ private static void CheckNamespaceNames(IEnumerable<INamespaceSymbol> namespaces
private static string GetSymbolDisplayString(IGrouping<string, ISymbol> group)
{
return string.Join(", ", group.Select(s => s.ToDisplayString()).OrderBy(StringComparer.InvariantCulture));
return string.Join(", ", group.Select(s => s.ToDisplayString()).OrderBy(k => k, StringComparer.InvariantCulture));
}
public static bool IsExternallyVisible(ISymbol symbol)
......
......@@ -2,9 +2,7 @@
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Naming
......
......@@ -4,7 +4,6 @@
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Performance
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Performance;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Performance
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Performance
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Reliability
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
internal static class CommonAccessibilityUtilities
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
......@@ -60,8 +60,8 @@ internal static bool TryConvertToUInt64(object value, SpecialType specialType, o
internal static bool TryGetEnumMemberValues(INamedTypeSymbol enumType, out IList<ulong> values)
{
Contract.ThrowIfNull(enumType);
Contract.ThrowIfFalse(enumType.TypeKind == TypeKind.Enum);
Debug.Assert(enumType != null);
Debug.Assert(enumType.TypeKind == TypeKind.Enum);
values = new List<ulong>();
foreach (IFieldSymbol field in enumType.GetMembers().Where(m => m.Kind == SymbolKind.Field && !m.IsImplicitlyDeclared))
......
......@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
internal static class IEnumerableExtensions
{
public static IEnumerable<T> Concat<T>(this IEnumerable<T> source, T value)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
foreach (var v in source)
{
yield return v;
}
yield return value;
}
public static ISet<T> ToSet<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
return new HashSet<T>(source, comparer);
}
public static ISet<T> ToSet<T>(this IEnumerable<T> source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
return source as ISet<T> ?? new HashSet<T>(source);
}
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> source, IComparer<T> comparer)
{
return source.OrderBy(t => t, comparer);
}
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> source, Comparison<T> compare)
{
return source.OrderBy(new ComparisonComparer<T>(compare));
}
public static IEnumerable<T> Order<T>(this IEnumerable<T> source) where T : IComparable<T>
{
return source.OrderBy((t1, t2) => t1.CompareTo(t2));
}
private static readonly Func<object, bool> NotNullTest = x => x != null;
public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> source) where T : class
{
if (source == null)
{
return ImmutableArray<T>.Empty;
}
return source.Where((Func<T, bool>)NotNullTest);
}
private class ComparisonComparer<T> : Comparer<T>
{
private readonly Comparison<T> compare;
public ComparisonComparer(Comparison<T> compare)
{
this.compare = compare;
}
public override int Compare(T x, T y)
{
return compare(x, y);
}
}
}
}
......@@ -2,7 +2,7 @@
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
internal static class INamedTypeSymbolExtensions
{
......
......@@ -2,7 +2,7 @@
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
public static class ISymbolExtensions
{
......@@ -31,5 +31,87 @@ public static bool IsErrorType(this ISymbol symbol)
symbol is ITypeSymbol &&
((ITypeSymbol)symbol).TypeKind == TypeKind.Error;
}
public static bool IsConstructor(this ISymbol symbol)
{
return (symbol as IMethodSymbol)?.MethodKind == MethodKind.Constructor;
}
public static bool IsDestructor(this ISymbol symbol)
{
return (symbol as IMethodSymbol)?.MethodKind == MethodKind.Destructor;
}
public static bool IsIndexer(this ISymbol symbol)
{
return (symbol as IPropertySymbol)?.IsIndexer == true;
}
public static bool IsUserDefinedOperator(this ISymbol symbol)
{
return (symbol as IMethodSymbol)?.MethodKind == MethodKind.UserDefinedOperator;
}
public static ImmutableArray<IParameterSymbol> GetParameters(this ISymbol symbol)
{
return symbol.TypeSwitch(
(IMethodSymbol m) => m.Parameters,
(IPropertySymbol p) => p.Parameters,
_ => ImmutableArray.Create<IParameterSymbol>());
}
public static SymbolVisibility GetResultantVisibility(this ISymbol symbol)
{
// Start by assuming it's visible.
var visibility = SymbolVisibility.Public;
switch (symbol.Kind)
{
case SymbolKind.Alias:
// Aliases are uber private. They're only visible in the same file that they
// were declared in.
return SymbolVisibility.Private;
case SymbolKind.Parameter:
// Parameters are only as visible as their containing symbol
return GetResultantVisibility(symbol.ContainingSymbol);
case SymbolKind.TypeParameter:
// Type Parameters are private.
return SymbolVisibility.Private;
}
while (symbol != null && symbol.Kind != SymbolKind.Namespace)
{
switch (symbol.DeclaredAccessibility)
{
// If we see anything private, then the symbol is private.
case Accessibility.NotApplicable:
case Accessibility.Private:
return SymbolVisibility.Private;
// If we see anything internal, then knock it down from public to
// internal.
case Accessibility.Internal:
case Accessibility.ProtectedAndInternal:
visibility = SymbolVisibility.Internal;
break;
// For anything else (Public, Protected, ProtectedOrInternal), the
// symbol stays at the level we've gotten so far.
}
symbol = symbol.ContainingSymbol;
}
return visibility;
}
}
public enum SymbolVisibility
{
Public,
Internal,
Private,
}
}
......@@ -2,9 +2,8 @@
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
public static class ITypeSymbolExtensions
{
......
......@@ -2,7 +2,7 @@
using System;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
internal static class ObjectExtensions
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
namespace Microsoft.CodeAnalysis
{
internal class SolutionChangeAction : CodeAction
{
private readonly string title;
private readonly Func<CancellationToken, Task<Solution>> createChangedSolution;
public SolutionChangeAction(string title, Func<CancellationToken, Task<Solution>> createChangedSolution)
{
this.title = title;
this.createChangedSolution = createChangedSolution;
}
public override string Title
{
get { return this.title; }
}
protected override Task<Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
{
return this.createChangedSolution(cancellationToken);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Shared.Extensions;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
......@@ -21,54 +22,66 @@ public sealed override ImmutableArray<string> FixableDiagnosticIds
protected abstract SyntaxNode GetFieldDeclarationNode(SyntaxNode node);
internal async override Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, CancellationToken cancellationToken)
internal override Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, CancellationToken cancellationToken)
{
IEnumerable<CodeAction> actions = null;
var actions = ImmutableArray.CreateBuilder<CodeAction>();
// Fix 1: Add a NonSerialized attribute to the field
var fieldNode = GetFieldDeclarationNode(nodeToFix);
if (fieldNode != null)
{
var generator = SyntaxGenerator.GetGenerator(document);
var attr = generator.Attribute(generator.TypeExpression(WellKnownTypes.NonSerializedAttribute(model.Compilation)));
var newNode = generator.AddAttributes(fieldNode, attr);
var newDocument = document.WithSyntaxRoot(root.ReplaceNode(fieldNode, newNode));
var codeAction = new MyDocumentCodeAction(FxCopFixersResources.AddNonSerializedAttribute, newDocument);
actions = SpecializedCollections.SingletonEnumerable(codeAction);
var codeAction = new MyDocumentCodeAction(FxCopFixersResources.AddNonSerializedAttribute,
async ct => await AddNonSerializedAttribute(document, model, root, fieldNode, generator).ConfigureAwait(false));
actions.Add(codeAction);
// Fix 2: If the type of the field is defined in source, then add the serializable attribute to the type.
var fieldSymbol = model.GetDeclaredSymbol(nodeToFix, cancellationToken) as IFieldSymbol;
var type = fieldSymbol.Type;
if (type.Locations.Any(l => l.IsInSource))
{
var typeDeclNode = type.DeclaringSyntaxReferences.First().GetSyntax(cancellationToken);
var typeCodeAction = new MySolutionCodeAction(FxCopFixersResources.AddSerializableAttribute,
async ct => await AddSerializableAttributeToType(document, model, generator, type, cancellationToken).ConfigureAwait(false));
var serializableAttr = generator.Attribute(generator.TypeExpression(WellKnownTypes.SerializableAttribute(model.Compilation)));
var newTypeDeclNode = generator.AddAttributes(typeDeclNode, serializableAttr);
var documentContainingNode = document.Project.Solution.GetDocument(typeDeclNode.SyntaxTree);
var docRoot = await documentContainingNode.GetSyntaxRootAsync(cancellationToken);
var newDocumentContainingNode = documentContainingNode.WithSyntaxRoot(docRoot.ReplaceNode(typeDeclNode, newTypeDeclNode));
var typeCodeAction = new MySolutionCodeAction(FxCopFixersResources.AddSerializableAttribute, newDocumentContainingNode.Project.Solution);
actions = actions.Concat(typeCodeAction);
actions.Add(typeCodeAction);
}
}
return actions;
return Task.FromResult<IEnumerable<CodeAction>>(actions.ToImmutable());
}
private static async Task<Solution> AddSerializableAttributeToType(Document document, SemanticModel model, SyntaxGenerator generator, ITypeSymbol type, CancellationToken cancellationToken)
{
var typeDeclNode = type.DeclaringSyntaxReferences.First().GetSyntax(cancellationToken);
var serializableAttr = generator.Attribute(generator.TypeExpression(WellKnownTypes.SerializableAttribute(model.Compilation)));
var newTypeDeclNode = generator.AddAttributes(typeDeclNode, serializableAttr);
var documentContainingNode = document.Project.Solution.GetDocument(typeDeclNode.SyntaxTree);
var docRoot = await documentContainingNode.GetSyntaxRootAsync(cancellationToken);
var newDocumentContainingNode = documentContainingNode.WithSyntaxRoot(docRoot.ReplaceNode(typeDeclNode, newTypeDeclNode));
return newDocumentContainingNode.Project.Solution;
}
private Task<Document> AddNonSerializedAttribute(Document document, SemanticModel model, SyntaxNode root, SyntaxNode fieldNode, SyntaxGenerator generator)
{
var attr = generator.Attribute(generator.TypeExpression(WellKnownTypes.NonSerializedAttribute(model.Compilation)));
var newNode = generator.AddAttributes(fieldNode, attr);
var newDocument = document.WithSyntaxRoot(root.ReplaceNode(fieldNode, newNode));
return Task.FromResult(newDocument);
}
private class MyDocumentCodeAction : CodeAction.DocumentChangeAction
private class MyDocumentCodeAction : DocumentChangeAction
{
public MyDocumentCodeAction(string title, Document newDocument) :
base(title, c => Task.FromResult(newDocument))
public MyDocumentCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument) :
base(title, createChangedDocument)
{
}
}
private class MySolutionCodeAction : CodeAction.SolutionChangeAction
private class MySolutionCodeAction : SolutionChangeAction
{
public MySolutionCodeAction(string title, Solution newSolution) :
base(title, c => Task.FromResult(newSolution))
public MySolutionCodeAction(string title, Func<CancellationToken, Task<Solution>> createChangedSolution) :
base(title, createChangedSolution)
{
}
}
......
......@@ -7,7 +7,6 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Usage
{
......
......@@ -34,22 +34,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Design
cancellationToken.ThrowIfCancellationRequested()
Dim root = Await document.GetSyntaxRootAsync(cancellationToken)
Dim classStatement = root.FindToken(span.Start).GetAncestor(Of ClassStatementSyntax)
Dim classStatement = root.FindToken(span.Start).Parent?.FirstAncestorOrSelf(Of ClassStatementSyntax)
If classStatement IsNot Nothing Then
Dim notInheritableKeyword = SyntaxFactory.Token(SyntaxKind.NotInheritableKeyword).WithAdditionalAnnotations(Formatter.Annotation)
Dim newClassStatement = classStatement.AddModifiers(notInheritableKeyword)
Dim newRoot = root.ReplaceNode(classStatement, newClassStatement)
context.RegisterCodeFix(
New MyCodeAction(String.Format(FxCopRulesResources.StaticHolderTypeIsNotStatic, classStatement.Identifier.Text), document.WithSyntaxRoot(newRoot)),
context.Diagnostics)
Dim title As String = String.Format(FxCopRulesResources.StaticHolderTypeIsNotStatic, classStatement.Identifier.Text)
Dim fix = New MyCodeAction(title, Function(ct) AddNotInheritableKeyword(document, root, classStatement))
context.RegisterCodeFix(fix, context.Diagnostics)
End If
End Function
Private Function AddNotInheritableKeyword(document As Document, root As SyntaxNode, classStatement As ClassStatementSyntax) As Task(Of Document)
Dim notInheritableKeyword = SyntaxFactory.Token(SyntaxKind.NotInheritableKeyword).WithAdditionalAnnotations(Formatter.Annotation)
Dim newClassStatement = classStatement.AddModifiers(notInheritableKeyword)
Dim newRoot = root.ReplaceNode(classStatement, newClassStatement)
Return Task.FromResult(document.WithSyntaxRoot(newRoot))
End Function
Private Class MyCodeAction
Inherits CodeAction.DocumentChangeAction
Inherits DocumentChangeAction
Public Sub New(title As String, newDocument As Document)
MyBase.New(title, Function(c) Task.FromResult(newDocument))
Public Sub New(title As String, createChangedDocument As Func(Of CancellationToken, Task(Of Document)))
MyBase.New(title, createChangedDocument)
End Sub
End Class
End Class
......
......@@ -30,7 +30,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Design
End If
End If
Throw ExceptionUtilities.Unreachable
Throw New InvalidOperationException("Unreachable code")
End Function
End Class
End Namespace
......@@ -20,7 +20,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Globalization
' if nothing can be fixed, return the unchanged node
Dim newRoot = root
Dim kind = nodeToFix.Kind()
Dim syntaxFactoryService = document.GetLanguageService(Of SyntaxGenerator)
Dim syntaxFactoryService = document.Project.LanguageServices.GetService(Of SyntaxGenerator)
Select Case kind
Case SyntaxKind.SimpleArgument
If Not CType(nodeToFix, SimpleArgumentSyntax).IsNamed Then
......@@ -41,7 +41,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Globalization
' String.Equals(a, b) => String.Equals(a, b, StringComparison.Ordinal)
' String.Compare(a, b) => String.Compare(a, b, StringComparison.Ordinal)
Dim identifier = CType(nodeToFix, IdentifierNameSyntax)
Dim invokeParent = identifier.GetAncestor(Of InvocationExpressionSyntax)()
Dim invokeParent = identifier.Parent?.FirstAncestorOrSelf(Of InvocationExpressionSyntax)()
If invokeParent IsNot Nothing Then
Dim methodSymbol = TryCast(model.GetSymbolInfo(identifier).Symbol, IMethodSymbol)
If methodSymbol IsNot Nothing AndAlso CanAddStringComparison(methodSymbol) Then
......
......@@ -43,7 +43,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Usage
Return Task.FromResult(document)
End If
Dim factory = document.GetLanguageService(Of SyntaxGenerator)()
Dim factory = document.Project.LanguageServices.GetService(Of SyntaxGenerator)()
' Handle a case where a local in the Dipose method with the same name by generating this (or ClassName) and simplifying it
Dim path = If(fieldSymbol.IsStatic, factory.IdentifierName(typeSymbol.MetadataName), factory.ThisExpression())
......
......@@ -235,16 +235,13 @@
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.EditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.Features" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.Workspaces.Desktop" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures.Text" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Features" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.FxCopAnalyzers" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.EditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.Features" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces.Desktop" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Workspaces.Desktop" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册