Skip to content

Commit 0529bde

Browse files
authored
Introduce NotNoneAttribute alias (#1420)
* Add global using NotNoneAttribute * Remove file-scope using Scripting.Runtime.NotNullAttribute * Rename CodeAnalysis.NotNullAttribute to NotNullOnReturnAttribute * Use NotNone in place of Microsoft.Scripting.Runtime.NotNull * Replace NotDynamicNull with NotNone * Replace NotNullOnReturn with NotNull * IronPythonAnalyzer: Compare symbols correctly * Update IronPythonAnalyzer messages * Enforce [NotNone] usage in IronPythonAnalyzer * Remove superfluous using Microsoft.Scripting.Runtime
1 parent da2da14 commit 0529bde

132 files changed

Lines changed: 1038 additions & 1129 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Directory.Build.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@
116116
<EnableNETAnalyzers>true</EnableNETAnalyzers>
117117
</PropertyGroup>
118118

119+
<ItemGroup>
120+
<Using Include="Microsoft.Scripting.Runtime.NotNullAttribute" Alias="NotNoneAttribute" />
121+
</ItemGroup>
122+
119123
<!-- Release -->
120124
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
121125
<DebugSymbols>false</DebugSymbols>

IronPythonAnalyzer/IronPythonAnalyzer/IronPythonAnalyzerAnalyzer.cs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ public class IronPythonAnalyzerAnalyzer : DiagnosticAnalyzer {
1919
public const string DiagnosticId = "IronPythonAnalyzer";
2020

2121
#pragma warning disable RS2008 // Enable analyzer release tracking
22-
private static readonly DiagnosticDescriptor Rule1 = new DiagnosticDescriptor("IPY01", title: "Parameter which is marked not nullable does not have the NotNullAttribute", messageFormat: "Parameter '{0}' does not have the NotNullAttribute", category: "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "Non-nullable reference type parameters should have the NotNullAttribute.");
23-
private static readonly DiagnosticDescriptor Rule2 = new DiagnosticDescriptor("IPY02", title: "Parameter which is marked nullable has the NotNullAttribute", messageFormat: "Parameter '{0}' should not have the NotNullAttribute", category: "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "Nullable reference type parameters should not have the NotNullAttribute.");
22+
private static readonly DiagnosticDescriptor Rule1 = new DiagnosticDescriptor("IPY01", title: "Parameter which is marked not nullable does not have the NotNoneAttribute", messageFormat: "Parameter '{0}' does not have the NotNoneAttribute", category: "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "Non-nullable reference type parameters should have the NotNoneAttribute.");
23+
private static readonly DiagnosticDescriptor Rule2 = new DiagnosticDescriptor("IPY02", title: "Parameter which is marked nullable has the NotNoneAttribute", messageFormat: "Parameter '{0}' should not have the NotNoneAttribute", category: "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "Nullable reference type parameters should not have the NotNoneAttribute.");
2424
private static readonly DiagnosticDescriptor Rule3 = new DiagnosticDescriptor("IPY03", title: "BytesLikeAttribute used on a not supported type", messageFormat: "Parameter '{0}' declared bytes-like on unsupported type '{1}'", category: "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "BytesLikeAttribute is only allowed on parameters of type IReadOnlyList<byte>, or IList<byte>.");
2525
private static readonly DiagnosticDescriptor Rule4 = new DiagnosticDescriptor("IPY04", title: "Call to PythonTypeOps.GetName", messageFormat: "Direct call to PythonTypeOps.GetName", category: "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "To obtain a name of a python type of a given object to display to a user, use PythonOps.GetPythonTypeName.");
26+
private static readonly DiagnosticDescriptor Rule5 = new DiagnosticDescriptor("IPY05", title: "DLR NotNullAttribute accessed without an alias", messageFormat: "Microsoft.Scripting.Runtime.NotNullAttribute should be accessed though alias 'NotNone'", category: "Usage", DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "NotNullAttribute is ambiguous between 'System.Diagnostics.CodeAnalysis.NotNullAttribute' and 'Microsoft.Scripting.Runtime.NotNullAttribute'. The latter should be accesses as 'NotNoneAttribute'.");
2627
#pragma warning restore RS2008 // Enable analyzer release tracking
2728

28-
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule1, Rule2, Rule3, Rule4); } }
29+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule1, Rule2, Rule3, Rule4, Rule5); } }
2930

3031
public override void Initialize(AnalysisContext context) {
3132
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
@@ -41,20 +42,18 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) {
4142
var pythonTypeAttributeSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.PythonTypeAttribute");
4243
var pythonModuleAttributeSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.PythonModuleAttribute");
4344

44-
#pragma warning disable RS1024 // Compare symbols correctly
45-
4645
if (methodSymbol.ContainingType.GetAttributes()
47-
.Any(x => x.AttributeClass.Equals(pythonTypeAttributeSymbol)) ||
46+
.Any(x => x.AttributeClass.Equals(pythonTypeAttributeSymbol, SymbolEqualityComparer.Default)) ||
4847
methodSymbol.ContainingAssembly.GetAttributes()
49-
.Where(x => x.AttributeClass.Equals(pythonModuleAttributeSymbol))
48+
.Where(x => x.AttributeClass.Equals(pythonModuleAttributeSymbol, SymbolEqualityComparer.Default))
5049
.Select(x => (INamedTypeSymbol)x.ConstructorArguments[1].Value)
51-
.Any(x => x.Equals(methodSymbol.ContainingType))) {
50+
.Any(x => x.Equals(methodSymbol.ContainingType, SymbolEqualityComparer.Default))) {
5251
var pythonHiddenAttributeSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.PythonHiddenAttribute");
53-
if (methodSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(pythonHiddenAttributeSymbol))) return;
52+
if (methodSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(pythonHiddenAttributeSymbol, SymbolEqualityComparer.Default))) return;
5453

5554
var codeContextSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.CodeContext");
5655
var siteLocalStorageSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.SiteLocalStorage");
57-
var notNullAttributeSymbol = context.Compilation.GetTypeByMetadataName("Microsoft.Scripting.Runtime.NotNullAttribute");
56+
var notNoneAttributeSymbol = context.Compilation.GetTypeByMetadataName("Microsoft.Scripting.Runtime.NotNullAttribute");
5857
var bytesLikeAttributeSymbol = context.Compilation.GetTypeByMetadataName("IronPython.Runtime.BytesLikeAttribute");
5958

6059
var byteType = context.Compilation.GetTypeByMetadataName("System.Byte");
@@ -64,24 +63,31 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context) {
6463
var ilistOfByteType = ilistType.Construct(byteType);
6564

6665
foreach (IParameterSymbol parameterSymbol in methodSymbol.Parameters) {
67-
if (parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(bytesLikeAttributeSymbol))
68-
&& !parameterSymbol.Type.Equals(ireadOnlyListOfByteType)
69-
&& !parameterSymbol.Type.Equals(ilistOfByteType)) {
66+
if (parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(bytesLikeAttributeSymbol, SymbolEqualityComparer.Default))
67+
&& !parameterSymbol.Type.Equals(ireadOnlyListOfByteType, SymbolEqualityComparer.Default)
68+
&& !parameterSymbol.Type.Equals(ilistOfByteType, SymbolEqualityComparer.Default)) {
7069
var diagnostic = Diagnostic.Create(Rule3, parameterSymbol.Locations[0], parameterSymbol.Name, parameterSymbol.Type.MetadataName);
7170
context.ReportDiagnostic(diagnostic);
7271
continue;
7372
}
73+
if (parameterSymbol.GetAttributes().FirstOrDefault(x => x.AttributeClass.Equals(notNoneAttributeSymbol, SymbolEqualityComparer.Default)) is AttributeData attr) {
74+
SyntaxNode node = attr.ApplicationSyntaxReference.GetSyntax(); // Async?
75+
if (node.GetLastToken().Text != "NotNone") {
76+
var diagnostic = Diagnostic.Create(Rule5, node.GetLocation());
77+
context.ReportDiagnostic(diagnostic);
78+
}
79+
}
7480
if (parameterSymbol.Type.IsValueType) continue;
75-
if (parameterSymbol.Type.Equals(codeContextSymbol)) continue;
81+
if (parameterSymbol.Type.Equals(codeContextSymbol, SymbolEqualityComparer.Default)) continue;
7682
if (SymbolEqualityComparer.Default.Equals(parameterSymbol.Type.BaseType, siteLocalStorageSymbol)) continue;
7783
if (parameterSymbol.NullableAnnotation == NullableAnnotation.NotAnnotated) {
78-
if (!parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(notNullAttributeSymbol))
84+
if (!parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(notNoneAttributeSymbol, SymbolEqualityComparer.Default))
7985
&& !parameterSymbol.GetAttributes().Any(x => IsAllowNull(x.AttributeClass))) {
8086
var diagnostic = Diagnostic.Create(Rule1, parameterSymbol.Locations[0], parameterSymbol.Name);
8187
context.ReportDiagnostic(diagnostic);
8288
}
8389
} else if (parameterSymbol.NullableAnnotation == NullableAnnotation.Annotated) {
84-
if (parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(notNullAttributeSymbol))
90+
if (parameterSymbol.GetAttributes().Any(x => x.AttributeClass.Equals(notNoneAttributeSymbol, SymbolEqualityComparer.Default))
8591
&& !parameterSymbol.GetAttributes().Any(x => IsDisallowNull(x.AttributeClass))) {
8692
var diagnostic = Diagnostic.Create(Rule2, parameterSymbol.Locations[0], parameterSymbol.Name);
8793
context.ReportDiagnostic(diagnostic);
@@ -96,9 +102,6 @@ bool IsDisallowNull(INamedTypeSymbol symbol) {
96102
return symbol.ToString() == "System.Diagnostics.CodeAnalysis.DisallowNullAttribute";
97103
}
98104
}
99-
100-
#pragma warning restore RS1024 // Compare symbols correctly
101-
102105
}
103106

104107
private static void AnalyzeInvocation(OperationAnalysisContext context) {

Src/IronPython.Modules/IterTools.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ private IEnumerator<object> LazyYielder() {
197197
public class compress : IterBase {
198198
private compress() { }
199199

200-
public compress(CodeContext/*!*/ context, [NotNull]object data, [NotNull]object selectors) {
200+
public compress(CodeContext/*!*/ context, [NotNone] object data, [NotNone] object selectors) {
201201
EnsureIterator(context, data);
202202
EnsureIterator(context, selectors);
203203
InnerEnumerator = LazyYielder(data, selectors);

Src/IronPython.Modules/ModuleOps.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
using System.Runtime.InteropServices;
1212

1313
using Microsoft.Scripting;
14-
using Microsoft.Scripting.Runtime;
1514
using Microsoft.Scripting.Utils;
1615

1716
using IronPython.Runtime;

0 commit comments

Comments
 (0)