提交 55ca82ff 编写于 作者: S Srivatsn Narayanan

Create a System.Runtime.InteropServices.Analyzers project

Three rules related to PInvokes are being moved here (CA1060, CA1401, CA2101).

The rules are fairly straightforward and dont branch out into C#\VB. The fixer for CA2101 needs to be able to fix DeclareSub statements in VB and needs language specific dlls.
上级 cb8bd025
......@@ -80,7 +80,6 @@
<Compile Include="Design\CSharpCA1003DiagnosticAnalyzer.cs" />
<Compile Include="Design\CSharpCA1024DiagnosticAnalyzer.cs" />
<Compile Include="Design\CSharpEnumWithFlagsDiagnosticAnalyzer.cs" />
<Compile Include="Globalization\CodeFixes\CA2101CSharpCodeFixProvider.cs" />
<Compile Include="Performance\CSharpCA1821DiagnosticAnalyzer.cs" />
<Compile Include="Reliability\CSharpCA2002DiagnosticAnalyzer.cs" />
<Compile Include="Usage\CodeFixes\CA2213CSharpCodeFixProvider.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.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Globalization;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Interoperability;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
using Microsoft.CodeAnalysis.LanguageServices;
namespace Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers.Globalization
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PInvokeDiagnosticAnalyzer.CA2101), Shared]
public class CA2101CSharpCodeFixProvider : CA2101CodeFixProviderBase
{
internal override Task<Document> GetUpdatedDocumentAsync(Document document, SemanticModel model, SyntaxNode root, SyntaxNode nodeToFix, Diagnostic diagnostic, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var charSetType = WellKnownTypes.CharSet(model.Compilation);
var dllImportType = WellKnownTypes.DllImportAttribute(model.Compilation);
var marshalAsType = WellKnownTypes.MarshalAsAttribute(model.Compilation);
var unmanagedType = WellKnownTypes.UnmanagedType(model.Compilation);
if (charSetType == null || dllImportType == null || marshalAsType == null || unmanagedType == null)
{
return Task.FromResult(document);
}
var syntaxFactoryService = document.Project.LanguageServices.GetService<SyntaxGenerator>();
// return the unchanged root if no fix is available
var newRoot = root;
if (nodeToFix.Kind() == SyntaxKind.Attribute)
{
// could be either a [DllImport] or [MarshalAs] attribute
var attribute = (AttributeSyntax)nodeToFix;
var attributeType = model.GetSymbolInfo(attribute, cancellationToken).Symbol;
var arguments = attribute.ArgumentList.Arguments;
if (dllImportType.Equals(attributeType.ContainingType))
{
// [DllImport] attribute, add or replace CharSet named parameter
var argumentValue = CreateCharSetArgument(syntaxFactoryService, charSetType).WithAdditionalAnnotations(Formatter.Annotation);
var namedParameter = arguments.FirstOrDefault(arg => arg.NameEquals != null && arg.NameEquals.Name.Identifier.Text == CharSetText);
if (namedParameter == null)
{
// add the parameter
namedParameter = SyntaxFactory.AttributeArgument(SyntaxFactory.NameEquals(CharSetText), null, (ExpressionSyntax)argumentValue)
.WithAdditionalAnnotations(Formatter.Annotation);
var newArguments = arguments.Add(namedParameter);
var newArgumentList = attribute.ArgumentList.WithArguments(newArguments);
newRoot = root.ReplaceNode(attribute.ArgumentList, newArgumentList);
}
else
{
// replace the parameter
var newNamedParameter = namedParameter.WithExpression((ExpressionSyntax)argumentValue);
newRoot = root.ReplaceNode(namedParameter, newNamedParameter);
}
}
else if (marshalAsType.Equals(attributeType.ContainingType) && arguments.Count == 1)
{
// [MarshalAs] attribute, replace the only argument
var newExpression = CreateMarshalAsArgument(syntaxFactoryService, unmanagedType)
.WithLeadingTrivia(arguments[0].GetLeadingTrivia())
.WithTrailingTrivia(arguments[0].GetTrailingTrivia());
var newArgument = arguments[0].WithExpression((ExpressionSyntax)newExpression);
newRoot = root.ReplaceNode(arguments[0], newArgument);
}
}
return Task.FromResult(document.WithSyntaxRoot(newRoot));
}
}
}
......@@ -107,7 +107,6 @@
<Compile Include="Design\CA1008DiagnosticAnalyzer.cs" />
<Compile Include="Design\CA1012DiagnosticAnalyzer.cs" />
<Compile Include="Design\CA1024DiagnosticAnalyzer.cs" />
<Compile Include="Design\CA1060DiagnosticAnalyzer.cs" />
<Compile Include="Design\CodeFixes\CA1008CodeFixProviderBase.cs" />
<Compile Include="Design\CodeFixes\CA1012CodeFixProvider.cs" />
<Compile Include="Design\CodeFixes\EnumWithFlagsCodeFixProviderBase.cs" />
......@@ -126,8 +125,6 @@
<DesignTime>True</DesignTime>
<DependentUpon>FxCopRulesResources.resx</DependentUpon>
</Compile>
<Compile Include="Globalization\CodeFixes\CA2101CodeFixProviderBase.cs" />
<Compile Include="Interoperability\PInvokeDiagnosticAnalyzer.cs" />
<Compile Include="MultipleCodeFixProviderBase.cs" />
<Compile Include="Naming\CA1708DiagnosticAnalyzer.cs" />
<Compile Include="Naming\CA1715DiagnosticAnalyzer.cs" />
......
......@@ -402,33 +402,6 @@ internal class FxCopRulesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Move P/Invokes to native methods class.
/// </summary>
internal static string MovePInvokesToNativeMethodsClass {
get {
return ResourceManager.GetString("MovePInvokesToNativeMethodsClass", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to P/Invoke method &apos;{0}&apos; should not be visible.
/// </summary>
internal static string PInvokeMethodShouldNotBeVisible {
get {
return ResourceManager.GetString("PInvokeMethodShouldNotBeVisible", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to P/Invokes should not be visible..
/// </summary>
internal static string PInvokesShouldNotBeVisible {
get {
return ResourceManager.GetString("PInvokesShouldNotBeVisible", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remove empty finalizers.
/// </summary>
......@@ -492,24 +465,6 @@ internal class FxCopRulesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Specify marshaling for P/Invoke string arguments.
/// </summary>
internal static string SpecifyMarshalingForPInvokeStringArguments {
get {
return ResourceManager.GetString("SpecifyMarshalingForPInvokeStringArguments", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to When marshaling strings as ANSI (or as Auto on Win9x), some characters may be changed. If best-fit mapping is on, strings that appear different in Unicode will be marshaled to identical ANSI strings, which may lead to incorrect security decisions. Turning best-fit mapping off reduces this risk, as all characters without equivalents are mapped to &apos;?&apos;. Also, note that CharSet.Ansi is the default setting for all string marshaling; Unicode marshaling must be specified explicitly, either as a CharSet setting of [rest of string was truncated]&quot;;.
/// </summary>
internal static string SpecifyMarshalingForPInvokeStringArgumentsDescription {
get {
return ResourceManager.GetString("SpecifyMarshalingForPInvokeStringArgumentsDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type &apos;{0}&apos; is a static holder type but is neither static nor NotInheritable.
/// </summary>
......
......@@ -153,15 +153,6 @@
<data name="RemoveEmptyFinalizers" xml:space="preserve">
<value>Remove empty finalizers</value>
</data>
<data name="PInvokeMethodShouldNotBeVisible" xml:space="preserve">
<value>P/Invoke method '{0}' should not be visible</value>
</data>
<data name="SpecifyMarshalingForPInvokeStringArguments" xml:space="preserve">
<value>Specify marshaling for P/Invoke string arguments</value>
</data>
<data name="MovePInvokesToNativeMethodsClass" xml:space="preserve">
<value>Move P/Invokes to native methods class</value>
</data>
<data name="DoNotLockOnWeakIdentity" xml:space="preserve">
<value>Do not lock on a reference of type '{0}' as it has weak identity. Replace that with a lock against an object with strong identity.</value>
</data>
......@@ -204,9 +195,6 @@
<data name="MarkISerializableTypesWithAttribute" xml:space="preserve">
<value>Mark ISerializable types with SerializableAttribute.</value>
</data>
<data name="PInvokesShouldNotBeVisible" xml:space="preserve">
<value>P/Invokes should not be visible.</value>
</data>
<data name="RethrowToPreserveStackDetails" xml:space="preserve">
<value>Rethrow to preserve stack details.</value>
</data>
......@@ -276,9 +264,6 @@
<data name="RemoveEmptyFinalizersDescription" xml:space="preserve">
<value>Finalizers should be avoided where possible, to avoid the additional performance overhead involved in tracking object lifetime.</value>
</data>
<data name="SpecifyMarshalingForPInvokeStringArgumentsDescription" xml:space="preserve">
<value>When marshaling strings as ANSI (or as Auto on Win9x), some characters may be changed. If best-fit mapping is on, strings that appear different in Unicode will be marshaled to identical ANSI strings, which may lead to incorrect security decisions. Turning best-fit mapping off reduces this risk, as all characters without equivalents are mapped to '?'. Also, note that CharSet.Ansi is the default setting for all string marshaling; Unicode marshaling must be specified explicitly, either as a CharSet setting of DllImport or StructLayout, or as a MarshalAs attribute with a Unicode (or system-dependent) UnmanagedType.</value>
</data>
<data name="CategoryDesign" xml:space="preserve">
<value>Design</value>
</data>
......
// 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 Microsoft.CodeAnalysis.Editing;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Globalization
{
public abstract class CA2101CodeFixProviderBase : CodeFixProviderBase
{
public sealed override ImmutableArray<string> FixableDiagnosticIds
{
get { return ImmutableArray.Create(Interoperability.PInvokeDiagnosticAnalyzer.CA2101); }
}
protected sealed override string GetCodeFixDescription(Diagnostic diagnostic)
{
return FxCopFixersResources.SpecifyMarshalingForPInvokeStringArguments;
}
protected const string CharSetText = "CharSet";
protected const string LPWStrText = "LPWStr";
protected const string UnicodeText = "Unicode";
internal SyntaxNode CreateMarshalAsArgument(SyntaxGenerator syntaxFactoryService, INamedTypeSymbol unmanagedType)
{
return syntaxFactoryService.MemberAccessExpression(
syntaxFactoryService.TypeExpression(unmanagedType), syntaxFactoryService.IdentifierName(LPWStrText));
}
internal SyntaxNode CreateCharSetArgument(SyntaxGenerator syntaxFactoryService, INamedTypeSymbol charSetType)
{
return syntaxFactoryService.MemberAccessExpression(
syntaxFactoryService.TypeExpression(charSetType), syntaxFactoryService.IdentifierName(UnicodeText));
}
}
}
......@@ -12,11 +12,6 @@
-Microsoft.Design#CA1012;
-Microsoft.Design#CA1052;
-Microsoft.Design#CA1053;
-Microsoft.Design#CA1060;
-Microsoft.Interoperability#CA1401;
-Microsoft.Globalization#CA2101;
-Microsoft.Naming#CA1708;
-Microsoft.Naming#CA1715;
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="Settings">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" />
<Import Project="..\..\..\..\..\build\VSL.Settings.Closed.targets" />
</ImportGroup>
<PropertyGroup>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A634B792-8504-4A2D-9149-4C9E4959F11C}</ProjectGuid>
<OutputType>Library</OutputType>
<AnalyzerProject>true</AnalyzerProject>
<RootNamespace>System.Runtime.InteropServices.CSharp.Analyzers</RootNamespace>
<AssemblyName>System.Runtime.InteropServices.CSharp.Analyzers</AssemblyName>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
<ProjectReference Include="..\..\..\..\Compilers\Core\Portable\CodeAnalysis.csproj">
<Project>{1ee8cad3-55f9-4d91-96b2-084641da9a6c}</Project>
<Name>CodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj">
<Project>{b501a547-c911-4a05-ac6e-274a50dff30e}</Project>
<Name>CSharpCodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Workspaces\Core\Portable\Workspaces.csproj">
<Project>{5f8d2414-064a-4b3a-9b42-8e2a04246be5}</Project>
<Name>Workspaces</Name>
</ProjectReference>
<ProjectReference Include="..\Core\SystemRuntimeInteropServicesAnalyzers.csproj">
<Project>{0a2bb2d6-883e-4c19-895a-0dc067436623}</Project>
<Name>SystemRuntimeInteropServicesAnalyzers</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Collections.Immutable, Version=1.1.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Composition.AttributedModel, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath>
</Reference>
<Reference Include="System.Composition.Convention, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath>
</Reference>
<Reference Include="System.Composition.Hosting, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll</HintPath>
</Reference>
<Reference Include="System.Composition.Runtime, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Composition.TypedParts, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="SpecifyMarshalingForPInvokeStringArguments.Fixer.cs" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\VSL.Imports.Closed.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
// 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.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace System.Runtime.InteropServices.Analyzers
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PInvokeDiagnosticAnalyzer.CA2101), Shared]
public class CSharpSpecifyMarshalingForPInvokeStringArgumentsFixer : SpecifyMarshalingForPInvokeStringArgumentsFixer
{
protected override bool IsAttribute(SyntaxNode node)
{
return node.IsKind(SyntaxKind.Attribute);
}
protected override SyntaxNode FindNamedArgument(IReadOnlyList<SyntaxNode> arguments, string argumentName)
{
return arguments.OfType<AttributeArgumentSyntax>().FirstOrDefault(arg => arg.NameEquals != null && arg.NameEquals.Name.Identifier.Text == argumentName);
}
protected override bool IsDeclareStatement(SyntaxNode node)
{
return false;
}
protected override Task<Document> FixDeclareStatement(Document document, SyntaxNode node, CancellationToken cancellationToken)
{
return Task.FromResult(document);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
<package id="Microsoft.Composition" version="1.0.27" targetFramework="net45" />
</packages>
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace System.Runtime.InteropServices.Analyzers
{
internal static class DiagnosticCategory
{
public static readonly string Design = nameof(Design);
public static readonly string Interoperability = nameof(Interoperability);
public static readonly string Globalization = nameof(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.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)
{
_title = title;
_createChangedDocument = createChangedDocument;
}
public override string Title
{
get { return _title; }
}
protected override Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
{
return _createChangedDocument(cancellationToken);
}
}
}
\ No newline at end of file
......@@ -4,46 +4,48 @@
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Design
namespace System.Runtime.InteropServices.Analyzers
{
/// <summary>
/// CA1060 - Move P/Invokes to native methods class
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class CA1060DiagnosticAnalyzer : AbstractNamedTypeAnalyzer
public sealed class MovePInvokesToNativeMethodsClassAnalyzer : DiagnosticAnalyzer
{
internal const string RuleId = "CA1060";
private static LocalizableString s_localizableTitleAndMessage = new LocalizableResourceString(nameof(FxCopRulesResources.MovePInvokesToNativeMethodsClass), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
private static LocalizableString s_localizableTitleAndMessage = new LocalizableResourceString(nameof(SystemRuntimeInteropServicesAnalyzersResources.MovePInvokesToNativeMethodsClass), SystemRuntimeInteropServicesAnalyzersResources.ResourceManager, typeof(SystemRuntimeInteropServicesAnalyzersResources));
internal static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId,
s_localizableTitleAndMessage,
s_localizableTitleAndMessage,
FxCopDiagnosticCategory.Design,
DiagnosticCategory.Design,
DiagnosticSeverity.Warning,
isEnabledByDefault: false,
helpLinkUri: "http://msdn.microsoft.com/library/ms182161.aspx",
customTags: DiagnosticCustomTags.Microsoft);
customTags: WellKnownDiagnosticTags.Telemetry);
private const string NativeMethodsText = "NativeMethods";
private const string SafeNativeMethodsText = "SafeNativeMethods";
private const string UnsafeNativeMethodsText = "UnsafeNativeMethods";
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
get
context.RegisterSymbolAction(symbolContext =>
{
return ImmutableArray.Create(Rule);
}
AnalyzeSymbol((INamedTypeSymbol)symbolContext.Symbol, symbolContext.Compilation, symbolContext.ReportDiagnostic);
}, SymbolKind.NamedType);
}
protected override void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action<Diagnostic> addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken)
private void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action<Diagnostic> addDiagnostic)
{
if (symbol.GetMembers().Any(member => IsDllImport(member)) && !IsTypeNamedCorrectly(symbol.Name))
{
addDiagnostic(symbol.CreateDiagnostic(Rule));
addDiagnostic(Diagnostic.Create(Rule, symbol.Locations.First(l => l.IsInSource)));
}
}
......
......@@ -2,11 +2,10 @@
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities;
namespace Microsoft.CodeAnalysis.FxCopAnalyzers.Interoperability
namespace System.Runtime.InteropServices.Analyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class PInvokeDiagnosticAnalyzer : DiagnosticAnalyzer
......@@ -14,28 +13,28 @@ public sealed class PInvokeDiagnosticAnalyzer : DiagnosticAnalyzer
public const string CA1401 = "CA1401";
public const string CA2101 = "CA2101";
private static LocalizableString s_localizableTitleCA1401 = new LocalizableResourceString(nameof(FxCopRulesResources.PInvokesShouldNotBeVisible), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
private static LocalizableString s_localizableMessageCA1401 = new LocalizableResourceString(nameof(FxCopRulesResources.PInvokeMethodShouldNotBeVisible), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
private static LocalizableString s_localizableTitleCA1401 = new LocalizableResourceString(nameof(SystemRuntimeInteropServicesAnalyzersResources.PInvokesShouldNotBeVisible), SystemRuntimeInteropServicesAnalyzersResources.ResourceManager, typeof(SystemRuntimeInteropServicesAnalyzersResources));
private static LocalizableString s_localizableMessageCA1401 = new LocalizableResourceString(nameof(SystemRuntimeInteropServicesAnalyzersResources.PInvokeMethodShouldNotBeVisible), SystemRuntimeInteropServicesAnalyzersResources.ResourceManager, typeof(SystemRuntimeInteropServicesAnalyzersResources));
internal static DiagnosticDescriptor RuleCA1401 = new DiagnosticDescriptor(CA1401,
s_localizableTitleCA1401,
s_localizableMessageCA1401,
FxCopDiagnosticCategory.Interoperability,
DiagnosticCategory.Interoperability,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: "http://msdn.microsoft.com/library/ms182209.aspx",
customTags: DiagnosticCustomTags.Microsoft);
customTags: WellKnownDiagnosticTags.Telemetry);
private static LocalizableString s_localizableMessageAndTitleCA2101 = new LocalizableResourceString(nameof(FxCopRulesResources.SpecifyMarshalingForPInvokeStringArguments), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
private static LocalizableString s_localizableDescriptionCA2101 = new LocalizableResourceString(nameof(FxCopRulesResources.SpecifyMarshalingForPInvokeStringArgumentsDescription), FxCopRulesResources.ResourceManager, typeof(FxCopRulesResources));
private static LocalizableString s_localizableMessageAndTitleCA2101 = new LocalizableResourceString(nameof(SystemRuntimeInteropServicesAnalyzersResources.SpecifyMarshalingForPInvokeStringArguments), SystemRuntimeInteropServicesAnalyzersResources.ResourceManager, typeof(SystemRuntimeInteropServicesAnalyzersResources));
private static LocalizableString s_localizableDescriptionCA2101 = new LocalizableResourceString(nameof(SystemRuntimeInteropServicesAnalyzersResources.SpecifyMarshalingForPInvokeStringArgumentsDescription), SystemRuntimeInteropServicesAnalyzersResources.ResourceManager, typeof(SystemRuntimeInteropServicesAnalyzersResources));
internal static DiagnosticDescriptor RuleCA2101 = new DiagnosticDescriptor(CA2101,
s_localizableMessageAndTitleCA2101,
s_localizableMessageAndTitleCA2101,
FxCopDiagnosticCategory.Globalization,
DiagnosticCategory.Globalization,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: s_localizableDescriptionCA2101,
helpLinkUri: "http://msdn.microsoft.com/library/ms182319.aspx",
customTags: DiagnosticCustomTags.Microsoft);
customTags: WellKnownDiagnosticTags.Telemetry);
private static readonly ImmutableArray<DiagnosticDescriptor> s_supportedDiagnostics = ImmutableArray.Create(RuleCA1401, RuleCA2101);
......@@ -119,7 +118,7 @@ public void AnalyzeSymbol(SymbolAnalysisContext context)
// CA1401 - PInvoke methods should not be visible
if (methodSymbol.DeclaredAccessibility == Accessibility.Public || methodSymbol.DeclaredAccessibility == Accessibility.Protected)
{
context.ReportDiagnostic(context.Symbol.CreateDiagnostic(RuleCA1401, methodSymbol.Name));
context.ReportDiagnostic(Diagnostic.Create(RuleCA1401, context.Symbol.Locations.First(l => l.IsInSource), methodSymbol.Name));
}
// CA2101 - Specify marshalling for PInvoke string arguments
......@@ -142,13 +141,13 @@ public void AnalyzeSymbol(SymbolAnalysisContext context)
{
// track the diagnostic on the [MarshalAs] attribute
var marshalAsLocation = GetAttributeLocation(marshalAsAttribute);
context.ReportDiagnostic(marshalAsLocation.CreateDiagnostic(RuleCA2101));
context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, marshalAsLocation));
}
else if (!appliedCA2101ToMethod)
{
// track the diagnostic on the [DllImport] attribute
appliedCA2101ToMethod = true;
context.ReportDiagnostic(defaultLocation.CreateDiagnostic(RuleCA2101));
context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, defaultLocation));
}
}
}
......@@ -158,7 +157,7 @@ public void AnalyzeSymbol(SymbolAnalysisContext context)
if (!appliedCA2101ToMethod && dllImportData.CharacterSet != CharSet.Unicode &&
(methodSymbol.ReturnType.SpecialType == SpecialType.System_String || methodSymbol.ReturnType.Equals(_stringBuilderType)))
{
context.ReportDiagnostic(defaultLocation.CreateDiagnostic(RuleCA2101));
context.ReportDiagnostic(Diagnostic.Create(RuleCA2101, defaultLocation));
}
}
}
......@@ -200,9 +199,11 @@ public void AnalyzeSymbol(SymbolAnalysisContext context)
case UnmanagedType.ByValTStr:
case UnmanagedType.LPTStr:
case UnmanagedType.TBStr:
return CharSet.Auto;
default:
return CharSet.None;
// CharSet.Auto and CharSet.None are not available in the portable
// profiles. We are not interested in those values for our analysis and so simply
// return null
return null;
}
}
......
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editing;
namespace System.Runtime.InteropServices.Analyzers
{
public abstract class SpecifyMarshalingForPInvokeStringArgumentsFixer : CodeFixProvider
{
protected const string CharSetText = "CharSet";
protected const string LPWStrText = "LPWStr";
protected const string UnicodeText = "Unicode";
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(PInvokeDiagnosticAnalyzer.CA2101);
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
var node = root.FindNode(context.Span);
if (node == null)
{
return;
}
var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
var charSetType = model.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.CharSet");
var dllImportType = model.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.DllImportAttribute");
var marshalAsType = model.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.MarshalAsAttribute");
var unmanagedType = model.Compilation.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedType");
if (charSetType == null || dllImportType == null || marshalAsType == null || unmanagedType == null)
{
return;
}
// We cannot have multiple overlapping diagnostics of this id.
var diagnostic = context.Diagnostics.Single();
if (IsAttribute(node))
{
context.RegisterCodeFix(new MyCodeAction(SystemRuntimeInteropServicesAnalyzersResources.SpecifyMarshalingForPInvokeStringArguments,
async ct => await FixAttributeArguments(context.Document, node, charSetType, dllImportType, marshalAsType, unmanagedType, ct).ConfigureAwait(false)),
diagnostic);
}
else if (IsDeclareStatement(node))
{
context.RegisterCodeFix(new MyCodeAction(SystemRuntimeInteropServicesAnalyzersResources.SpecifyMarshalingForPInvokeStringArguments,
async ct => await FixDeclareStatement(context.Document, node, ct).ConfigureAwait(false)),
diagnostic);
}
}
protected abstract bool IsAttribute(SyntaxNode node);
protected abstract bool IsDeclareStatement(SyntaxNode node);
protected abstract Task<Document> FixDeclareStatement(Document document, SyntaxNode node, CancellationToken cancellationToken);
protected abstract SyntaxNode FindNamedArgument(IReadOnlyList<SyntaxNode> arguments, string argumentName);
private async Task<Document> FixAttributeArguments(Document document, SyntaxNode attributeDeclaration,
INamedTypeSymbol charSetType, INamedTypeSymbol dllImportType, INamedTypeSymbol marshalAsType, INamedTypeSymbol unmanagedType, CancellationToken cancellationToken)
{
var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);
var generator = editor.Generator;
var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
// could be either a [DllImport] or [MarshalAs] attribute
var attributeType = model.GetSymbolInfo(attributeDeclaration, cancellationToken).Symbol;
var arguments = generator.GetAttributeArguments(attributeDeclaration);
if (dllImportType.Equals(attributeType.ContainingType))
{
// [DllImport] attribute, add or replace CharSet named parameter
var argumentValue = generator.MemberAccessExpression(
generator.TypeExpression(charSetType),
generator.IdentifierName(UnicodeText));
var newCharSetArgument = generator.AttributeArgument(CharSetText, argumentValue);
var charSetArgument = FindNamedArgument(arguments, CharSetText);
if (charSetArgument == null)
{
// add the parameter
editor.AddAttributeArgument(attributeDeclaration, newCharSetArgument);
}
else
{
// replace the parameter
editor.ReplaceNode(charSetArgument, newCharSetArgument);
}
}
else if (marshalAsType.Equals(attributeType.ContainingType) && arguments.Count == 1)
{
// [MarshalAs] attribute, replace the only argument
var newArgument = generator.AttributeArgument(
generator.MemberAccessExpression(
generator.TypeExpression(unmanagedType),
generator.IdentifierName(LPWStrText)));
editor.ReplaceNode(arguments[0], newArgument);
}
return editor.GetChangedDocument();
}
private class MyCodeAction : DocumentChangeAction
{
public MyCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument)
: base(title, createChangedDocument)
{
}
}
}
}
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!--
This file contains the rules that have been implemented in this package and therefore should be disabled for the binary FxCop.
When a new rule is implemented in this package, make sure to add an entry below to disable that rule in FxCop to avoid duplicate
issues.
The format is -[Category]#[ID]
-->
<PropertyGroup>
<CodeAnalysisRuleSetOverrides>$(CodeAnalysisRuleSetOverrides);
-Microsoft.Design#CA1060;
-Microsoft.Interoperability#CA1401;
-Microsoft.Globalization#CA2101;
</CodeAnalysisRuleSetOverrides>
</PropertyGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="Settings">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" />
<Import Project="..\..\..\..\..\build\VSL.Settings.Closed.targets" />
</ImportGroup>
<PropertyGroup>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0A2BB2D6-883E-4C19-895A-0DC067436623}</ProjectGuid>
<OutputType>Library</OutputType>
<AnalyzerProject>true</AnalyzerProject>
<RootNamespace>System.Runtime.InteropServices.Analyzers</RootNamespace>
<AssemblyName>System.Runtime.InteropServices.Analyzers</AssemblyName>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
<ProjectReference Include="..\..\..\..\Compilers\Core\Portable\CodeAnalysis.csproj">
<Project>{1ee8cad3-55f9-4d91-96b2-084641da9a6c}</Project>
<Name>CodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Workspaces\Core\Portable\Workspaces.csproj">
<Project>{5f8d2414-064a-4b3a-9b42-8e2a04246be5}</Project>
<Name>Workspaces</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Collections.Immutable, Version=1.1.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Composition.AttributedModel, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<InternalsVisibleToTest Include="System.Runtime.InteropServices.Analyzers.UnitTests" />
</ItemGroup>
<ItemGroup>
<Content Include="System.Runtime.InteropServices.Analyzers.Common.props">
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="DiagnosticCategory.cs" />
<Compile Include="DocumentChangeAction.cs" />
<Compile Include="MovePInvokesToNativeMethodsClass.cs" />
<Compile Include="PInvokeDiagnosticAnalyzer.cs" />
<Compile Include="SpecifyMarshalingForPInvokeStringArguments.Fixer.cs" />
<Compile Include="SystemRuntimeInteropServicesAnalyzersResources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>SystemRuntimeInteropServicesAnalyzersResources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="SystemRuntimeInteropServicesAnalyzersResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>SystemRuntimeInteropServicesAnalyzersResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup />
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\VSL.Imports.Closed.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace System.Runtime.InteropServices.Analyzers {
using System;
using System.Reflection;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SystemRuntimeInteropServicesAnalyzersResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SystemRuntimeInteropServicesAnalyzersResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Runtime.InteropServices.Analyzers.SystemRuntimeInteropServicesAnalyzersRes" +
"ources", typeof(SystemRuntimeInteropServicesAnalyzersResources).GetTypeInfo().Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Make the P\Invoke method internal.
/// </summary>
internal static string MarkPInvokeMethodAsInternal {
get {
return ResourceManager.GetString("MarkPInvokeMethodAsInternal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Move P/Invokes to native methods class.
/// </summary>
internal static string MovePInvokesToNativeMethodsClass {
get {
return ResourceManager.GetString("MovePInvokesToNativeMethodsClass", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to P/Invoke method &apos;{0}&apos; should not be visible.
/// </summary>
internal static string PInvokeMethodShouldNotBeVisible {
get {
return ResourceManager.GetString("PInvokeMethodShouldNotBeVisible", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to P/Invokes should not be visible..
/// </summary>
internal static string PInvokesShouldNotBeVisible {
get {
return ResourceManager.GetString("PInvokesShouldNotBeVisible", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Specify marshaling for P/Invoke string arguments.
/// </summary>
internal static string SpecifyMarshalingForPInvokeStringArguments {
get {
return ResourceManager.GetString("SpecifyMarshalingForPInvokeStringArguments", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to When marshaling strings as ANSI (or as Auto on Win9x), some characters may be changed. If best-fit mapping is on, strings that appear different in Unicode will be marshaled to identical ANSI strings, which may lead to incorrect security decisions. Turning best-fit mapping off reduces this risk, as all characters without equivalents are mapped to &apos;?&apos;. Also, note that CharSet.Ansi is the default setting for all string marshaling; Unicode marshaling must be specified explicitly, either as a CharSet setting of [rest of string was truncated]&quot;;.
/// </summary>
internal static string SpecifyMarshalingForPInvokeStringArgumentsDescription {
get {
return ResourceManager.GetString("SpecifyMarshalingForPInvokeStringArgumentsDescription", resourceCulture);
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="MarkPInvokeMethodAsInternal" xml:space="preserve">
<value>Make the P\Invoke method internal</value>
</data>
<data name="MovePInvokesToNativeMethodsClass" xml:space="preserve">
<value>Move P/Invokes to native methods class</value>
</data>
<data name="PInvokeMethodShouldNotBeVisible" xml:space="preserve">
<value>P/Invoke method '{0}' should not be visible</value>
</data>
<data name="PInvokesShouldNotBeVisible" xml:space="preserve">
<value>P/Invokes should not be visible.</value>
</data>
<data name="SpecifyMarshalingForPInvokeStringArguments" xml:space="preserve">
<value>Specify marshaling for P/Invoke string arguments</value>
</data>
<data name="SpecifyMarshalingForPInvokeStringArgumentsDescription" xml:space="preserve">
<value>When marshaling strings as ANSI (or as Auto on Win9x), some characters may be changed. If best-fit mapping is on, strings that appear different in Unicode will be marshaled to identical ANSI strings, which may lead to incorrect security decisions. Turning best-fit mapping off reduces this risk, as all characters without equivalents are mapped to '?'. Also, note that CharSet.Ansi is the default setting for all string marshaling; Unicode marshaling must be specified explicitly, either as a CharSet setting of DllImport or StructLayout, or as a MarshalAs attribute with a Unicode (or system-dependent) UnmanagedType.</value>
</data>
</root>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
<package id="Microsoft.Composition" version="1.0.27" targetFramework="net45" />
</packages>
// 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.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Design;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
namespace Microsoft.CodeAnalysis.UnitTests.Design
namespace System.Runtime.InteropServices.Analyzers.UnitTests
{
public class CA1060Tests : DiagnosticAnalyzerTestBase
public class MovePInvokesToNativeMethodsClassTests : DiagnosticAnalyzerTestBase
{
#region Verifiers
protected override DiagnosticAnalyzer GetBasicDiagnosticAnalyzer()
{
return new CA1060DiagnosticAnalyzer();
return new MovePInvokesToNativeMethodsClassAnalyzer();
}
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
{
return new CA1060DiagnosticAnalyzer();
return new MovePInvokesToNativeMethodsClassAnalyzer();
}
private static DiagnosticResult CSharpResult(int line, int column)
{
return GetCSharpResultAt(line, column, CA1060DiagnosticAnalyzer.Rule.Id, CA1060DiagnosticAnalyzer.Rule.MessageFormat.ToString());
return GetCSharpResultAt(line, column, MovePInvokesToNativeMethodsClassAnalyzer.Rule.Id, MovePInvokesToNativeMethodsClassAnalyzer.Rule.MessageFormat.ToString());
}
private static DiagnosticResult BasicResult(int line, int column)
{
return GetBasicResultAt(line, column, CA1060DiagnosticAnalyzer.Rule.Id, CA1060DiagnosticAnalyzer.Rule.MessageFormat.ToString());
return GetBasicResultAt(line, column, MovePInvokesToNativeMethodsClassAnalyzer.Rule.Id, MovePInvokesToNativeMethodsClassAnalyzer.Rule.MessageFormat.ToString());
}
#endregion
......
// 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.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Interoperability;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
namespace Microsoft.CodeAnalysis.UnitTests.Interoperability
namespace System.Runtime.InteropServices.Analyzers.UnitTests
{
public class PInvokeDiagnosticAnalyzerTests : DiagnosticAnalyzerTestBase
{
......
// 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.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers.Globalization;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FxCopAnalyzers.Interoperability;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Globalization;
using Microsoft.CodeAnalysis.UnitTests;
using Xunit;
namespace Microsoft.CodeAnalysis.UnitTests.Interoperability
namespace System.Runtime.InteropServices.Analyzers.UnitTests
{
public class CA2101FixerTests : CodeFixTestBase
public class SpecifyMarshalingForPInvokeStringArgumentsFixerTests : CodeFixTestBase
{
#region Verifiers
......@@ -26,12 +24,12 @@ protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
protected override CodeFixProvider GetBasicCodeFixProvider()
{
return new CA2101BasicCodeFixProvider();
return new BasicSpecifyMarshalingForPInvokeStringArgumentsFixer();
}
protected override CodeFixProvider GetCSharpCodeFixProvider()
{
return new CA2101CSharpCodeFixProvider();
return new CSharpSpecifyMarshalingForPInvokeStringArgumentsFixer();
}
#endregion
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="Settings">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" />
<Import Project="..\..\..\..\..\build\VSL.Settings.Closed.targets" />
</ImportGroup>
<PropertyGroup>
<Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
<ProjectGuid>{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>System.Runtime.InteropServices.Analyzers.UnitTests</RootNamespace>
<AssemblyName>System.Runtime.InteropServices.Analyzers.UnitTests</AssemblyName>
<Nonshipping>true</Nonshipping>
<SolutionDir Condition="'$(SolutionDir)' == '' OR '$(SolutionDir)' == '*Undefined*'">..\..\..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\..\..\..\Compilers\Core\Desktop\CodeAnalysis.Desktop.csproj">
<Project>{dfa21ca1-7f96-47ee-940c-069858e81727}</Project>
<Name>CodeAnalysis.Desktop</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Compilers\Core\Portable\CodeAnalysis.csproj">
<Project>{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}</Project>
<Name>CodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Compilers\CSharp\Portable\CSharpCodeAnalysis.csproj">
<Project>{B501A547-C911-4A05-AC6E-274A50DFF30E}</Project>
<Name>CSharpCodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Compilers\VisualBasic\Desktop\BasicCodeAnalysis.Desktop.vbproj">
<Project>{73f3e2c5-d742-452e-b9e1-20732ddbc75d}</Project>
<Name>BasicCodeAnalysis.Desktop</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Compilers\VisualBasic\Portable\BasicCodeAnalysis.vbproj">
<Project>{2523D0E6-DF32-4A3E-8AE0-A19BFFAE2EF6}</Project>
<Name>BasicCodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Test\Utilities\TestUtilities.csproj">
<Project>{76C6F005-C89D-4348-BB4A-391898DBEB52}</Project>
<Name>TestUtilities</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Workspaces\CSharp\Portable\CSharpWorkspace.csproj">
<Project>{21B239D0-D144-430F-A394-C066D58EE267}</Project>
<Name>CSharpWorkspace</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Workspaces\VisualBasic\Portable\BasicWorkspace.vbproj">
<Project>{57CA988D-F010-4BF2-9A2E-07D6DCD2FF2C}</Project>
<Name>BasicWorkspace</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Workspaces\Core\Portable\Workspaces.csproj">
<Project>{5F8D2414-064A-4B3A-9B42-8E2A04246BE5}</Project>
<Name>Workspaces</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\Test\Utilities\DiagnosticsTestUtilities.csproj">
<Project>{0A0621F2-D1DC-47FF-B643-C6646557505E}</Project>
<Name>DiagnosticsTestUtilities</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Compilers\Test\Resources\Core\CompilerTestResources.vbproj">
<Project>{7FE6B002-89D8-4298-9B1B-0B5C247DD1FD}</Project>
<Name>CompilerTestResources</Name>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\Core\SystemRuntimeInteropServicesAnalyzers.csproj">
<Project>{0a2bb2d6-883e-4c19-895a-0dc067436623}</Project>
<Name>SystemRuntimeInteropServicesAnalyzers</Name>
</ProjectReference>
<ProjectReference Include="..\CSharp\CSharpSystemRuntimeInteropServicesAnalyzers.csproj">
<Project>{a634b792-8504-4a2d-9149-4c9e4959f11c}</Project>
<Name>CSharpSystemRuntimeInteropServicesAnalyzers</Name>
</ProjectReference>
<ProjectReference Include="..\VisualBasic\BasicSystemRuntimeInteropServicesAnalyzers.vbproj">
<Project>{ede9e796-e0a4-42e9-8b82-97b664b9343e}</Project>
<Name>BasicSystemRuntimeInteropServicesAnalyzers</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="xunit">
<HintPath>..\..\..\..\..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="SpecifyMarshalingForPInvokeStringArgumentsTests.Fixer.cs" />
<Compile Include="MovePInvokesToNativeMethodsClassTests.cs" />
<Compile Include="PInvokeDiagnosticAnalyzerTests.cs" />
</ItemGroup>
<ItemGroup />
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\VSL.Imports.Closed.targets" />
<Import Project="..\..\..\..\..\build\Roslyn.Toolsets.Xunit.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
<package id="xunit" version="1.9.2" targetFramework="net45" />
</packages>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="Settings">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Settings.targets" />
<Import Project="..\..\..\..\..\build\VSL.Settings.Closed.targets" />
</ImportGroup>
<PropertyGroup>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EDE9E796-E0A4-42E9-8B82-97B664B9343E}</ProjectGuid>
<OutputType>Library</OutputType>
<AnalyzerProject>true</AnalyzerProject>
<AssemblyName>System.Runtime.InteropServices.VisualBasic.Analyzers</AssemblyName>
<ProjectTypeGuids>{14182A97-F7F0-4C62-8B27-98AA8AE2109A};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
<ProjectReference Include="..\..\..\..\Compilers\Core\Portable\CodeAnalysis.csproj">
<Project>{1ee8cad3-55f9-4d91-96b2-084641da9a6c}</Project>
<Name>CodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Compilers\VisualBasic\Portable\BasicCodeAnalysis.vbproj">
<Project>{2523d0e6-df32-4a3e-8ae0-a19bffae2ef6}</Project>
<Name>BasicCodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Workspaces\Core\Portable\Workspaces.csproj">
<Project>{5f8d2414-064a-4b3a-9b42-8e2a04246be5}</Project>
<Name>Workspaces</Name>
</ProjectReference>
<ProjectReference Include="..\Core\SystemRuntimeInteropServicesAnalyzers.csproj">
<Project>{0a2bb2d6-883e-4c19-895a-0dc067436623}</Project>
<Name>SystemRuntimeInteropServicesAnalyzers</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Collections.Immutable, Version=1.1.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Composition.AttributedModel, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath>
</Reference>
<Reference Include="System.Composition.Convention, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath>
</Reference>
<Reference Include="System.Composition.Hosting, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll</HintPath>
</Reference>
<Reference Include="System.Composition.Runtime, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Composition.TypedParts, Version=1.0.27.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="SpecifyMarshalingForPInvokeStringArguments.Fixer.vb" />
</ItemGroup>
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\..\build\VSL.Imports.Closed.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports System.Threading
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace System.Runtime.InteropServices.Analyzers
<ExportCodeFixProvider(LanguageNames.CSharp, Name:=PInvokeDiagnosticAnalyzer.CA2101), [Shared]>
Public Class BasicSpecifyMarshalingForPInvokeStringArgumentsFixer
Inherits SpecifyMarshalingForPInvokeStringArgumentsFixer
Protected Overrides Function IsAttribute(node As SyntaxNode) As Boolean
Return node.IsKind(SyntaxKind.Attribute)
End Function
Protected Overrides Function FindNamedArgument(arguments As IReadOnlyList(Of SyntaxNode), argumentName As String) As SyntaxNode
Return Aggregate arg In arguments.OfType(Of SimpleArgumentSyntax)
Where arg.IsNamed
Into FirstOrDefault(arg.NameColonEquals.Name.Identifier.Text = argumentName)
End Function
Protected Overrides Function IsDeclareStatement(node As SyntaxNode) As Boolean
Return node.IsKind(SyntaxKind.DeclareFunctionStatement) OrElse
node.IsKind(SyntaxKind.DeclareSubStatement)
End Function
Protected Overrides Async Function FixDeclareStatement(document As Document, node As SyntaxNode, cancellationToken As CancellationToken) As Task(Of Document)
Dim editor = Await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(False)
Dim decl = CType(node, DeclareStatementSyntax)
Dim newCharSetKeyword = SyntaxFactory.Token(SyntaxKind.UnicodeKeyword).
WithLeadingTrivia(decl.CharsetKeyword.LeadingTrivia).
WithTrailingTrivia(decl.CharsetKeyword.TrailingTrivia).
WithAdditionalAnnotations(Formatter.Annotation)
Dim newDecl = decl.WithCharsetKeyword(newCharSetKeyword)
editor.ReplaceNode(decl, newDecl)
Return editor.GetChangedDocument()
End Function
End Class
End Namespace
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
<package id="Microsoft.Composition" version="1.0.27" targetFramework="net45" />
</packages>
......@@ -87,14 +87,11 @@
<Compile Include="Design\CA1024Tests.cs" />
<Compile Include="Design\CA1052Tests.cs" />
<Compile Include="Design\CA1053Tests.cs" />
<Compile Include="Design\CA1060Tests.cs" />
<Compile Include="Design\CodeFixes\CA1008FixerTests.cs" />
<Compile Include="Design\CodeFixes\CA1012FixerTests.cs" />
<Compile Include="Design\CodeFixes\EnumWithFlagsAttributesRulesFixerTests.cs" />
<Compile Include="Design\EnumWithFlagsAttributeRulesTests.cs" />
<Compile Include="Globalization\CodeFixes\CA2101FixerTests.cs" />
<Compile Include="HardeningAnalyzer\HardeningAnalyzerTests.cs" />
<Compile Include="Interoperability\PInvokeDiagnosticAnalyzerTests.cs" />
<Compile Include="Naming\CA1708Tests.cs" />
<Compile Include="Naming\CA1715Tests.cs" />
<Compile Include="Performance\CA1821Tests.cs" />
......@@ -131,6 +128,9 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Interoperability\" />
</ItemGroup>
<ImportGroup Label="Targets">
<Import Project="..\..\..\Tools\Microsoft.CodeAnalysis.Toolset.Open\Targets\VSL.Imports.targets" />
<Import Project="..\..\..\..\build\VSL.Imports.Closed.targets" />
......
......@@ -102,7 +102,6 @@
<Compile Include="Design\CodeFixes\CA1008BasicCodeFixProvider.vb" />
<Compile Include="Design\CodeFixes\CA1052BasicCodeFixProvider.vb" />
<Compile Include="Design\CodeFixes\EnumWithFlagsBasicCodeFixProvider.vb" />
<Compile Include="Globalization\CodeFixes\CA2101BasicCodeFixProvider.vb" />
<Compile Include="Performance\BasicCA1821DiagnosticAnalyzer.vb" />
<Compile Include="Reliability\BasicCA2002DiagnosticAnalyzer.vb" />
<Compile Include="Usage\BasicCA2200DiagnosticAnalyzer.vb" />
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.FxCopAnalyzers.Globalization
Imports Microsoft.CodeAnalysis.FxCopAnalyzers.Interoperability
Imports Microsoft.CodeAnalysis.FxCopAnalyzers.Utilities
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.FxCopAnalyzers.Globalization
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PInvokeDiagnosticAnalyzer.CA2101), [Shared]>
Public Class CA2101BasicCodeFixProvider
Inherits CA2101CodeFixProviderBase
Friend Overrides Function GetUpdatedDocumentAsync(document As Document, model As SemanticModel, root As SyntaxNode, nodeToFix As SyntaxNode, diagnostic As Diagnostic, cancellationToken As CancellationToken) As Task(Of Document)
cancellationToken.ThrowIfCancellationRequested()
Dim charSetType = WellKnownTypes.CharSet(model.Compilation)
Dim dllImportType = WellKnownTypes.DllImportAttribute(model.Compilation)
Dim marshalAsType = WellKnownTypes.MarshalAsAttribute(model.Compilation)
Dim unmanagedType = WellKnownTypes.UnmanagedType(model.Compilation)
If charSetType Is Nothing OrElse dllImportType Is Nothing OrElse marshalAsType Is Nothing OrElse unmanagedType Is Nothing Then
Return Task.FromResult(document)
End If
Dim syntaxFactoryService = document.Project.LanguageServices.GetService(Of SyntaxGenerator)()
' return the unchanged root if no fix is available
Dim newRoot = root
Select Case nodeToFix.Kind()
Case SyntaxKind.Attribute
' could be either a <DllImport> Or <MarshalAs> attribute
Dim attribute = CType(nodeToFix, AttributeSyntax)
Dim attributeType = model.GetSymbolInfo(attribute).Symbol
Dim arguments = attribute.ArgumentList.Arguments
If dllImportType.Equals(attributeType.ContainingType) Then
' <DllImport> attribute, add Or replace CharSet named parameter
Dim argumentValue = CreateCharSetArgument(syntaxFactoryService, charSetType).WithAdditionalAnnotations(Formatter.Annotation)
Dim namedParameter = Aggregate arg In arguments.OfType(Of SimpleArgumentSyntax)
Where arg.IsNamed
Into FirstOrDefault(arg.NameColonEquals.Name.Identifier.Text = CharSetText)
If namedParameter Is Nothing Then
' add the parameter
namedParameter = SyntaxFactory.SimpleArgument(SyntaxFactory.NameColonEquals(SyntaxFactory.IdentifierName(SyntaxFactory.Identifier(CharSetText))), CType(argumentValue, ExpressionSyntax)).
WithAdditionalAnnotations(Formatter.Annotation)
Dim newArguments = arguments.Add(namedParameter)
Dim newArgumentList = attribute.ArgumentList.WithArguments(newArguments)
newRoot = root.ReplaceNode(attribute.ArgumentList, newArgumentList)
Else
' replace the parameter
Dim newNamedParameter = namedParameter.WithExpression(CType(argumentValue, ExpressionSyntax))
newRoot = root.ReplaceNode(namedParameter, newNamedParameter)
End If
ElseIf marshalAsType.Equals(attributeType.ContainingType) AndAlso arguments.Count = 1 Then
' <MarshalAs> attribute, replace the only argument
Dim argument = CType(arguments(0), SimpleArgumentSyntax)
Dim newExpression = CreateMarshalAsArgument(syntaxFactoryService, unmanagedType).
WithLeadingTrivia(argument.GetLeadingTrivia()).
WithTrailingTrivia(argument.GetTrailingTrivia())
Dim newArgument = argument.WithExpression(CType(newExpression, ExpressionSyntax))
newRoot = root.ReplaceNode(argument, newArgument)
End If
Case SyntaxKind.DeclareFunctionStatement, SyntaxKind.DeclareSubStatement
Dim decl = CType(nodeToFix, DeclareStatementSyntax)
Dim newCharSetKeyword = SyntaxFactory.Token(SyntaxKind.UnicodeKeyword).
WithLeadingTrivia(decl.CharsetKeyword.LeadingTrivia).
WithTrailingTrivia(decl.CharsetKeyword.TrailingTrivia).
WithAdditionalAnnotations(Formatter.Annotation)
Dim newDecl = decl.WithCharsetKeyword(newCharSetKeyword)
newRoot = root.ReplaceNode(decl, newDecl)
End Select
Return Task.FromResult(document.WithSyntaxRoot(newRoot))
End Function
End Class
End Namespace
......@@ -331,6 +331,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vbc", "Compilers\VisualBasi
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pdb2Xml", "Tools\Source\Pdb2Xml\Pdb2Xml.csproj", "{CF450DCE-D12B-4A11-8D2D-A7A125372C48}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "System.Runtime.InteropServices.Analyzers", "System.Runtime.InteropServices.Analyzers", "{32BCFD38-B44B-4E4F-AFC6-90ABAF32C465}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemRuntimeInteropServicesAnalyzers", "Diagnostics\FxCop\System.Runtime.InteropServices.Analyzers\Core\SystemRuntimeInteropServicesAnalyzers.csproj", "{0A2BB2D6-883E-4C19-895A-0DC067436623}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemRuntimeInteropServicesAnalyzersTest", "Diagnostics\FxCop\System.Runtime.InteropServices.Analyzers\Test\SystemRuntimeInteropServicesAnalyzersTest.csproj", "{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpSystemRuntimeInteropServicesAnalyzers", "Diagnostics\FxCop\System.Runtime.InteropServices.Analyzers\CSharp\CSharpSystemRuntimeInteropServicesAnalyzers.csproj", "{A634B792-8504-4A2D-9149-4C9E4959F11C}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "BasicSystemRuntimeInteropServicesAnalyzers", "Diagnostics\FxCop\System.Runtime.InteropServices.Analyzers\VisualBasic\BasicSystemRuntimeInteropServicesAnalyzers.vbproj", "{EDE9E796-E0A4-42E9-8B82-97B664B9343E}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Compilers\Core\AnalyzerDriver\AnalyzerDriver.projitems*{edc68a0e-c68d-4a74-91b7-bf38ec909888}*SharedItemsImports = 4
......@@ -2428,6 +2438,70 @@ Global
{CF450DCE-D12B-4A11-8D2D-A7A125372C48}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{CF450DCE-D12B-4A11-8D2D-A7A125372C48}.Release|x64.ActiveCfg = Release|Any CPU
{CF450DCE-D12B-4A11-8D2D-A7A125372C48}.Release|x64.Build.0 = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|ARM.ActiveCfg = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|ARM.Build.0 = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|x64.ActiveCfg = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Debug|x64.Build.0 = Debug|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|Any CPU.Build.0 = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|ARM.ActiveCfg = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|ARM.Build.0 = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|x64.ActiveCfg = Release|Any CPU
{0A2BB2D6-883E-4C19-895A-0DC067436623}.Release|x64.Build.0 = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|ARM.ActiveCfg = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|ARM.Build.0 = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|x64.ActiveCfg = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Debug|x64.Build.0 = Debug|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|Any CPU.ActiveCfg = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|Any CPU.Build.0 = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|ARM.ActiveCfg = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|ARM.Build.0 = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|x64.ActiveCfg = Release|Any CPU
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115}.Release|x64.Build.0 = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|ARM.Build.0 = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|x64.ActiveCfg = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Debug|x64.Build.0 = Debug|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|Any CPU.Build.0 = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|ARM.ActiveCfg = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|ARM.Build.0 = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|x64.ActiveCfg = Release|Any CPU
{A634B792-8504-4A2D-9149-4C9E4959F11C}.Release|x64.Build.0 = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|ARM.ActiveCfg = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|ARM.Build.0 = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|x64.ActiveCfg = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Debug|x64.Build.0 = Debug|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|Any CPU.Build.0 = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|ARM.ActiveCfg = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|ARM.Build.0 = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|x64.ActiveCfg = Release|Any CPU
{EDE9E796-E0A4-42E9-8B82-97B664B9343E}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -2582,5 +2656,10 @@ Global
{21446697-E359-41D9-B39D-40ADA2B20823} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37}
{E58EE9D7-1239-4961-A0C1-F9EC3952C4C1} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37}
{CF450DCE-D12B-4A11-8D2D-A7A125372C48} = {64BDF58B-41BA-A19E-0D34-B5FA598403B6}
{32BCFD38-B44B-4E4F-AFC6-90ABAF32C465} = {24E8CBFA-38D2-486F-B772-C10AB2DC7F01}
{0A2BB2D6-883E-4C19-895A-0DC067436623} = {32BCFD38-B44B-4E4F-AFC6-90ABAF32C465}
{94A18486-A90F-4E7A-AD1C-EFF26B5CE115} = {32BCFD38-B44B-4E4F-AFC6-90ABAF32C465}
{A634B792-8504-4A2D-9149-4C9E4959F11C} = {32BCFD38-B44B-4E4F-AFC6-90ABAF32C465}
{EDE9E796-E0A4-42E9-8B82-97B664B9343E} = {32BCFD38-B44B-4E4F-AFC6-90ABAF32C465}
EndGlobalSection
EndGlobal
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册