Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions illink.sln
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ILLink.Shared", "src\ILLink.Shared\ILLink.Shared.shproj", "{92F5E753-2179-46DC-BDCE-736858C18DC7}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\ILLink.Shared\ILLink.Shared.projitems*{92f5e753-2179-46dc-bdce-736858c18dc7}*SharedItemsImports = 13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To educate myself whats this code doing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was generated by VS. Couldn't find anything particularly interesting; looks like the first entry (13) is referencing the shared project itself and the bellow ones are the projects that use the shared proj.

src\ILLink.Shared\ILLink.Shared.projitems*{dd28e2b1-057b-4b4d-a04d-b2ebd9e76e46}*SharedItemsImports = 5
src\ILLink.Shared\ILLink.Shared.projitems*{f1a44a78-34ee-408b-8285-9a26f0e7d4f2}*SharedItemsImports = 5
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Expand Down
4 changes: 2 additions & 2 deletions src/ILLink.CodeFix/BaseAttributeCodeFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ private static async Task<Document> AddAttribute (
CancellationToken cancellationToken)
{
var semanticModel = await document.GetSemanticModelAsync (cancellationToken).ConfigureAwait (false);
if (semanticModel is null) {
if (semanticModel is null)
return document;
}

var newAttribute = generator
.Attribute (generator.TypeExpression (AttributeSymbol), attrArgs)
.WithAdditionalAnnotations (
Expand Down
10 changes: 8 additions & 2 deletions src/ILLink.CodeFix/RequiresAssemblyFilesCodeFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading.Tasks;
using ILLink.CodeFixProvider;
using ILLink.RoslynAnalyzer;
using ILLink.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -18,8 +20,12 @@ namespace ILLink.CodeFix
[ExportCodeFixProvider (LanguageNames.CSharp, Name = nameof (RequiresAssemblyFilesCodeFixProvider)), Shared]
public class RequiresAssemblyFilesCodeFixProvider : BaseAttributeCodeFixProvider
{
public sealed override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create (RequiresAssemblyFilesAnalyzer.IL3000, RequiresAssemblyFilesAnalyzer.IL3001, RequiresAssemblyFilesAnalyzer.IL3002);
public ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (
DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.AvoidAssemblyLocationInSingleFile),
DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.AvoidAssemblyGetFilesInSingleFile),
DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresAssemblyFiles));

public sealed override ImmutableArray<string> FixableDiagnosticIds => SupportedDiagnostics.Select (dd => dd.Id).ToImmutableArray ();

private protected override LocalizableString CodeFixTitle => new LocalizableResourceString (nameof (Resources.RequiresAssemblyFilesCodeFixTitle), Resources.ResourceManager, typeof (Resources));

Expand Down
7 changes: 5 additions & 2 deletions src/ILLink.CodeFix/RequiresUnreferencedCodeCodeFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading.Tasks;
using ILLink.CodeFixProvider;
using ILLink.RoslynAnalyzer;
using ILLink.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -18,8 +20,9 @@ namespace ILLink.CodeFix
[ExportCodeFixProvider (LanguageNames.CSharp, Name = nameof (RequiresUnreferencedCodeCodeFixProvider)), Shared]
public class RequiresUnreferencedCodeCodeFixProvider : BaseAttributeCodeFixProvider
{
public sealed override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create (RequiresUnreferencedCodeAnalyzer.IL2026);
public ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresUnreferencedCode));

public sealed override ImmutableArray<string> FixableDiagnosticIds => SupportedDiagnostics.Select (dd => dd.Id).ToImmutableArray ();

private protected override LocalizableString CodeFixTitle => new LocalizableResourceString (nameof (Resources.RequiresUnreferencedCodeCodeFixTitle), Resources.ResourceManager, typeof (Resources));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
using System.Collections.Immutable;
using System.Composition;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using ILLink.CodeFixProvider;
using ILLink.RoslynAnalyzer;
using ILLink.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -22,7 +23,11 @@ public class UnconditionalSuppressMessageCodeFixProvider : BaseAttributeCodeFixP
public const string FullyQualifiedUnconditionalSuppressMessageAttribute = "System.Diagnostics.CodeAnalysis." + UnconditionalSuppressMessageAttribute;

public sealed override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create (RequiresUnreferencedCodeAnalyzer.IL2026, RequiresAssemblyFilesAnalyzer.IL3000, RequiresAssemblyFilesAnalyzer.IL3001, RequiresAssemblyFilesAnalyzer.IL3002);
=> (new DiagnosticId[] {
DiagnosticId.RequiresUnreferencedCode,
DiagnosticId.AvoidAssemblyLocationInSingleFile,
DiagnosticId.AvoidAssemblyGetFilesInSingleFile,
DiagnosticId.RequiresAssemblyFiles }).Select (d => d.AsString ()).ToImmutableArray ();

private protected override LocalizableString CodeFixTitle => new LocalizableResourceString (nameof (Resources.UconditionalSuppressMessageCodeFixTitle), Resources.ResourceManager, typeof (Resources));

Expand Down
68 changes: 68 additions & 0 deletions src/ILLink.RoslynAnalyzer/DiagnosticDescriptors.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using ILLink.Shared;
using Microsoft.CodeAnalysis;

namespace ILLink.RoslynAnalyzer
{
public static class DiagnosticDescriptors
{
public static DiagnosticDescriptor GetDiagnosticDescriptor (DiagnosticId diagnosticId)
{
var diagnosticString = new DiagnosticString (diagnosticId);
return new DiagnosticDescriptor (diagnosticId.AsString (),
diagnosticString.GetTitleFormat (),
diagnosticString.GetMessageFormat (),
GetDiagnosticCategory (diagnosticId),
DiagnosticSeverity.Warning,
true);
}

public static DiagnosticDescriptor GetDiagnosticDescriptor (DiagnosticId diagnosticId,
LocalizableResourceString? lrsTitle = null,
LocalizableResourceString? lrsMessage = null,
string? diagnosticCategory = null,
DiagnosticSeverity diagnosticSeverity = DiagnosticSeverity.Warning,
bool isEnabledByDefault = true,
string? helpLinkUri = null)
{
if (lrsTitle == null || lrsMessage == null) {
var diagnosticString = new DiagnosticString (diagnosticId);
return new DiagnosticDescriptor (diagnosticId.AsString (),
diagnosticString.GetTitleFormat (),
diagnosticString.GetMessageFormat (),
diagnosticCategory ?? GetDiagnosticCategory (diagnosticId),
diagnosticSeverity,
isEnabledByDefault,
helpLinkUri);
}

return new DiagnosticDescriptor (diagnosticId.AsString (),
lrsTitle!,
lrsMessage!,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if one of the title or message is null?

diagnosticCategory ?? GetDiagnosticCategory (diagnosticId),
diagnosticSeverity,
isEnabledByDefault,
helpLinkUri);
}

static string GetDiagnosticCategory (DiagnosticId diagnosticId)
{
switch ((int) diagnosticId) {
case > 2000 and < 3000:
return DiagnosticCategory.Trimming;

case >= 3000 and <= 6000:
return DiagnosticCategory.SingleFile;

default:
break;
}

throw new ArgumentException ($"The provided diagnostic id '{diagnosticId}' does not fall into the range of supported warning codes 2001 to 6000 (inclusive).");
}
}
}
57 changes: 11 additions & 46 deletions src/ILLink.RoslynAnalyzer/RequiresAssemblyFilesAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using System;
using System.Collections.Immutable;
using System.Linq;
using ILLink.Shared;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
Expand All @@ -14,58 +13,21 @@ namespace ILLink.RoslynAnalyzer
[DiagnosticAnalyzer (LanguageNames.CSharp)]
public sealed class RequiresAssemblyFilesAnalyzer : RequiresAnalyzerBase
{
public const string IL3000 = nameof (IL3000);
public const string IL3001 = nameof (IL3001);
public const string IL3002 = nameof (IL3002);
public const string IL3003 = nameof (IL3003);

private const string RequiresAssemblyFilesAttribute = nameof (RequiresAssemblyFilesAttribute);
public const string RequiresAssemblyFilesAttributeFullyQualifiedName = "System.Diagnostics.CodeAnalysis." + RequiresAssemblyFilesAttribute;

static readonly DiagnosticDescriptor s_locationRule = new DiagnosticDescriptor (
IL3000,
new LocalizableResourceString (nameof (SharedStrings.AvoidAssemblyLocationInSingleFileTitle),
SharedStrings.ResourceManager, typeof (SharedStrings)),
new LocalizableResourceString (nameof (SharedStrings.AvoidAssemblyLocationInSingleFileMessage),
SharedStrings.ResourceManager, typeof (SharedStrings)),
DiagnosticCategory.SingleFile,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
static readonly DiagnosticDescriptor s_locationRule = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.AvoidAssemblyLocationInSingleFile,
helpLinkUri: "https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/il3000");

static readonly DiagnosticDescriptor s_getFilesRule = new DiagnosticDescriptor (
IL3001,
new LocalizableResourceString (nameof (SharedStrings.AvoidAssemblyGetFilesInSingleFileTitle),
SharedStrings.ResourceManager, typeof (SharedStrings)),
new LocalizableResourceString (nameof (SharedStrings.AvoidAssemblyGetFilesInSingleFileMessage),
SharedStrings.ResourceManager, typeof (SharedStrings)),
DiagnosticCategory.SingleFile,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
static readonly DiagnosticDescriptor s_getFilesRule = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.AvoidAssemblyGetFilesInSingleFile,
helpLinkUri: "https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/il3001");

static readonly DiagnosticDescriptor s_requiresAssemblyFilesRule = new DiagnosticDescriptor (
IL3002,
new LocalizableResourceString (nameof (SharedStrings.RequiresAssemblyFilesTitle),
SharedStrings.ResourceManager, typeof (SharedStrings)),
new LocalizableResourceString (nameof (SharedStrings.RequiresAssemblyFilesMessage),
SharedStrings.ResourceManager, typeof (SharedStrings)),
DiagnosticCategory.SingleFile,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
static readonly DiagnosticDescriptor s_requiresAssemblyFilesRule = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresAssemblyFiles,
helpLinkUri: "https://docs.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/il3002");

static readonly DiagnosticDescriptor s_requiresAttributeMismatch = new DiagnosticDescriptor (
IL3003,
new LocalizableResourceString (nameof (SharedStrings.RequiresAttributeMismatchTitle),
SharedStrings.ResourceManager, typeof (SharedStrings)),
new LocalizableResourceString (nameof (SharedStrings.RequiresAttributeMismatchMessage),
SharedStrings.ResourceManager, typeof (SharedStrings)),
DiagnosticCategory.Trimming,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
static readonly DiagnosticDescriptor s_requiresAssembyFilesAttributeMismatch = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresAssembyFilesAttributeMismatch);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (s_locationRule, s_getFilesRule, s_requiresAssemblyFilesRule, s_requiresAttributeMismatch);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (s_locationRule, s_getFilesRule, s_requiresAssemblyFilesRule, s_requiresAssembyFilesAttributeMismatch);

private protected override string RequiresAttributeName => RequiresAssemblyFilesAttribute;

Expand All @@ -75,16 +37,18 @@ public sealed class RequiresAssemblyFilesAnalyzer : RequiresAnalyzerBase

private protected override DiagnosticDescriptor RequiresDiagnosticRule => s_requiresAssemblyFilesRule;

private protected override DiagnosticDescriptor RequiresAttributeMismatch => s_requiresAttributeMismatch;
private protected override DiagnosticDescriptor RequiresAttributeMismatch => s_requiresAssembyFilesAttributeMismatch;

protected override bool IsAnalyzerEnabled (AnalyzerOptions options, Compilation compilation)
{
var isSingleFileAnalyzerEnabled = options.GetMSBuildPropertyValue (MSBuildPropertyOptionNames.EnableSingleFileAnalyzer, compilation);
if (!string.Equals (isSingleFileAnalyzerEnabled?.Trim (), "true", StringComparison.OrdinalIgnoreCase))
return false;

var includesAllContent = options.GetMSBuildPropertyValue (MSBuildPropertyOptionNames.IncludeAllContentForSelfExtract, compilation);
if (string.Equals (includesAllContent?.Trim (), "true", StringComparison.OrdinalIgnoreCase))
return false;

return true;
}

Expand All @@ -94,10 +58,10 @@ protected override ImmutableArray<ISymbol> GetSpecialIncompatibleMembers (Compil

var assemblyType = compilation.GetTypeByMetadataName ("System.Reflection.Assembly");
if (assemblyType != null) {
// properties
// Properties
ImmutableArrayOperations.AddIfNotNull (dangerousPatternsBuilder, ImmutableArrayOperations.TryGetSingleSymbol<IPropertySymbol> (assemblyType.GetMembers ("Location")));

// methods
// Methods
dangerousPatternsBuilder.AddRange (assemblyType.GetMembers ("GetFile").OfType<IMethodSymbol> ());
dangerousPatternsBuilder.AddRange (assemblyType.GetMembers ("GetFiles").OfType<IMethodSymbol> ());
}
Expand All @@ -120,6 +84,7 @@ protected override bool ReportSpecialIncompatibleMembersDiagnostic (OperationAna
operationContext.ReportDiagnostic (Diagnostic.Create (s_locationRule, operationContext.Operation.Syntax.GetLocation (), member.GetDisplayName ()));
return true;
}

return false;
}

Expand Down
27 changes: 4 additions & 23 deletions src/ILLink.RoslynAnalyzer/RequiresUnreferencedCodeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,13 @@ namespace ILLink.RoslynAnalyzer
[DiagnosticAnalyzer (LanguageNames.CSharp)]
public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase
{
public const string IL2026 = nameof (IL2026);
public const string IL2046 = nameof (IL2046);
const string RequiresUnreferencedCodeAttribute = nameof (RequiresUnreferencedCodeAttribute);
public const string FullyQualifiedRequiresUnreferencedCodeAttribute = "System.Diagnostics.CodeAnalysis." + RequiresUnreferencedCodeAttribute;

static readonly DiagnosticDescriptor s_requiresUnreferencedCodeRule = new DiagnosticDescriptor (
IL2026,
new LocalizableResourceString (nameof (SharedStrings.RequiresUnreferencedCodeTitle),
SharedStrings.ResourceManager, typeof (SharedStrings)),
new LocalizableResourceString (nameof (SharedStrings.RequiresUnreferencedCodeMessage),
SharedStrings.ResourceManager, typeof (SharedStrings)),
DiagnosticCategory.Trimming,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);
static readonly DiagnosticDescriptor s_requiresUnreferencedCodeRule = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresUnreferencedCode);
static readonly DiagnosticDescriptor s_requiresUnreferencedCodeAttributeMismatch = DiagnosticDescriptors.GetDiagnosticDescriptor (DiagnosticId.RequiresUnreferencedCodeAttributeMismatch);

static readonly DiagnosticDescriptor s_requiresAttributeMismatch = new DiagnosticDescriptor (
IL2046,
new LocalizableResourceString (nameof (SharedStrings.RequiresAttributeMismatchTitle),
SharedStrings.ResourceManager, typeof (SharedStrings)),
new LocalizableResourceString (nameof (SharedStrings.RequiresAttributeMismatchMessage),
SharedStrings.ResourceManager, typeof (SharedStrings)),
DiagnosticCategory.Trimming,
DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (s_requiresUnreferencedCodeRule, s_requiresAttributeMismatch);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create (s_requiresUnreferencedCodeRule, s_requiresUnreferencedCodeAttributeMismatch);

private protected override string RequiresAttributeName => RequiresUnreferencedCodeAttribute;

Expand All @@ -48,7 +29,7 @@ public sealed class RequiresUnreferencedCodeAnalyzer : RequiresAnalyzerBase

private protected override DiagnosticDescriptor RequiresDiagnosticRule => s_requiresUnreferencedCodeRule;

private protected override DiagnosticDescriptor RequiresAttributeMismatch => s_requiresAttributeMismatch;
private protected override DiagnosticDescriptor RequiresAttributeMismatch => s_requiresUnreferencedCodeAttributeMismatch;

protected override bool IsAnalyzerEnabled (AnalyzerOptions options, Compilation compilation)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace ILLink.RoslynAnalyzer
namespace ILLink.Shared
{
internal static class DiagnosticCategory
{
Expand Down
20 changes: 20 additions & 0 deletions src/ILLink.Shared/DiagnosticId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace ILLink.Shared
{
public enum DiagnosticId
{
// Linker diagnostic ids.
RequiresUnreferencedCode = 2026,
RequiresUnreferencedCodeAttributeMismatch = 2046,

// Single-file diagnostic ids.
AvoidAssemblyLocationInSingleFile = 3000,
AvoidAssemblyGetFilesInSingleFile = 3001,
RequiresAssemblyFiles = 3002,
RequiresAssembyFilesAttributeMismatch = 3003
}

public static class DiagnosticIdExtensions
{
public static string AsString (this DiagnosticId diagnosticId) => $"IL{(int) diagnosticId}";
}
}
25 changes: 25 additions & 0 deletions src/ILLink.Shared/DiagnosticString.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace ILLink.Shared
{
public readonly struct DiagnosticString
{
readonly string _titleFormat;
readonly string _messageFormat;

public DiagnosticString (DiagnosticId diagnosticId)
{
var resourceManager = SharedStrings.ResourceManager;
_titleFormat = resourceManager.GetString ($"{diagnosticId}Title");
_messageFormat = resourceManager.GetString ($"{diagnosticId}Message");
}

public string GetMessage (params string[] args) =>
string.Format (_messageFormat, args);

public string GetMessageFormat () => _messageFormat;

public string GetTitle (params string[] args) =>
string.Format (_titleFormat, args);

public string GetTitleFormat () => _titleFormat;
}
}
3 changes: 3 additions & 0 deletions src/ILLink.Shared/ILLink.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<Import_RootNamespace>ILLink.Shared</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)DiagnosticCategory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DiagnosticId.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DiagnosticString.cs" />
<Compile Include="$(MSBuildThisFileDirectory)MessageFormat.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
Loading