Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Diagnostic rules #685

Merged
merged 11 commits into from
Jan 26, 2021
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ global.json
nuget/Microsoft.Windows.CsWinRT.Prerelease.targets
*.binlog
vs_buildtools.exe
.buildtools
.buildtools
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
; Shipped analyzer releases
; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md

33 changes: 33 additions & 0 deletions src/Authoring/WinRT.SourceGenerator/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
; Unshipped analyzer release
; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md

### New Rules
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
CsWinRT1000 | Usage | Error | Property should have public `get` method
CsWinRT1001 | Usage | Error | Namespaces should match the assembly namespace or be child namespaces of the assembly namespace
CsWinRT1002 | Usage | Error | Namespaces cannot differ only by case
CsWinRT1003 | Usage | Error | Component must have at least on public type
CsWinRT1004 | Usage | Error | Public types cannot be generic
CsWinRT1005 | Usage | Error | Classes exposed to CsWinRT should be sealed
CsWinRT1006 | Usage | Error | Do not expose unsupported type
CsWinRT1007 | Usage | Error | Structs should contain at least one public field
CsWinRT1008 | Usage | Error | Interfaces should not inherit interfaces that are not valid in Windows Runtime
CsWinRT1009 | Usage | Error | Class should not have multiple constructors that take the same amount of parameters
CsWinRT1010 | Usage | Error | Methods should not use parameter names that conflict with generated parameter names
CsWinRT1011 | Usage | Error | Structs should not have private fields
CsWinRT1012 | Usage | Error | Structs should not have a constant field
CsWinRT1013 | Usage | Error | Structs should only contain basic types or other structs
CsWinRT1014 | Usage | Error | Types should not overload an operator
CsWinRT1015 | Usage | Error | Do not use `DefaultOverloadAttribute` more than once for a set of overloads
CsWinRT1016 | Usage | Error | Exactly one overload should be marked as DefaultOverload
CsWinRT1017 | Usage | Error | Array types should be one dimensional, not jagged
CsWinRT1018 | Usage | Error | Array types should be one dimensional
CsWinRT1019 | Usage | Error | Do not use the `System.Array` type for array parameters or array return values
CsWinRT1020 | Usage | Error | Do not pass parameters by `ref`
CsWinRT1021 | Usage | Error | Array parameters should not be marked `InAttribute` or `OutAttribute`
CsWinRT1022 | Usage | Error | Parameters should not be marked `InAttribute` or `OutAttribute`
CsWinRT1023 | Usage | Error | Array parameters should not be marked both `ReadOnlyArrayAttribute` and `WriteOnlyArrayAttribute`
CsWinRT1024 | Usage | Error | Array parameter marked `out` should not be declared `ReadOnlyArrayAttribute`
CsWinRT1025 | Usage | Error | Array parameter should be marked either `ReadOnlyArrayAttribute` or `WriteOnlyArrayAttribute`
CsWinRT1026 | Usage | Error | Non-array parameter should not be marked `ReadOnlyArrayAttribute` or `WriteOnlyArrayAttribute`
2 changes: 1 addition & 1 deletion src/Authoring/WinRT.SourceGenerator/DiagnosticHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ private void ParameterHasAttributeErrors(MethodDeclarationSyntax method)
// Nothing can be marked `ref`
if (HasModifier(param, SyntaxKind.RefKeyword))
{
Report(WinRTRules.RefParameterFound, method.GetLocation(), param.Identifier);
Report(WinRTRules.RefParameterFound, method.GetLocation(), method.Identifier, param.Identifier);
}

if (ParamHasInOrOutAttribute(param))
Expand Down
32 changes: 16 additions & 16 deletions src/Authoring/WinRT.SourceGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ private static string GetCsWinRTWindowsMetadata(GeneratorExecutionContext contex
return cswinrtWindowsMetadata;
}

private static string GetCsWinRTDependentMetadata(GeneratorExecutionContext context)
{
context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTAuthoringInputs", out var winmds);
return winmds;
}
private static string GetCsWinRTDependentMetadata(GeneratorExecutionContext context)
{
context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.CsWinRTAuthoringInputs", out var winmds);
return winmds;
}

private string GetTempFolder(bool clearSourceFilesFromFolder = false)
{
if(_tempFolder == null || !File.Exists(_tempFolder))
Expand Down Expand Up @@ -113,15 +113,15 @@ private void GenerateSources(GeneratorExecutionContext context)
string winmdFile = GetWinmdOutputFile(context);
string outputDir = GetTempFolder(true);
string windowsMetadata = GetCsWinRTWindowsMetadata(context);
string winmds = GetCsWinRTDependentMetadata(context);
string arguments = string.Format(
"-component -input \"{0}\" -input {1} -include {2} -output \"{3}\" -input {4} -verbose",
winmdFile,
windowsMetadata,
assemblyName,
outputDir,
winmds);
string winmds = GetCsWinRTDependentMetadata(context);

string arguments = string.Format(
"-component -input \"{0}\" -input {1} -include {2} -output \"{3}\" -input {4} -verbose",
winmdFile,
windowsMetadata,
assemblyName,
outputDir,
winmds);
Logger.Log("Running " + cswinrtExe + " " + arguments);

var processInfo = new ProcessStartInfo
Expand Down Expand Up @@ -201,7 +201,7 @@ public void Execute(GeneratorExecutionContext context)
{
return;
}

Logger.Initialize(context);


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,11 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.8.0-4.20472.6" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.0" PrivateAssets="all" />
</ItemGroup>


<!-- Analyzer Release Tracking -->
<ItemGroup>
<AdditionalFiles Include="AnalyzerReleases.Shipped.md" />
<AdditionalFiles Include="AnalyzerReleases.Unshipped.md" />
</ItemGroup>

</Project>
95 changes: 48 additions & 47 deletions src/Authoring/WinRT.SourceGenerator/WinRTRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,124 +18,125 @@ private static DiagnosticDescriptor MakeRule(string id, string title, string mes
category: "Usage",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
helpLinkUri: "https://docs.microsoft.com/en-us/previous-versions/hh977010(v=vs.110)");
helpLinkUri: "https://github.com/microsoft/CsWinRT/tree/master/src/Authoring/WinRT.SourceGenerator/AnalyzerReleases.Unshipped.md");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We may want this to be AnalyzerReleases.Shipped.md, but I am not sure when we consider a version of our SourceGenerator analyzer "released"

}

public static DiagnosticDescriptor PrivateGetterRule = MakeRule(
"WME",
"CsWinRT1000",
"Property must have public getter",
"Property '{0}' does not have a public getter method. Windows Metadata does not support setter-only properties.");
"Property '{0}' does not have a public getter method. Windows Runtime does not support setter-only properties.");

public static DiagnosticDescriptor DisjointNamespaceRule = MakeRule(
"WME1044",
"CsWinRT1001",
"Namespace is disjoint from main (winmd) namespace",
"A public type has a namespace ('{1}') that shares no common prefix with other namespaces ('{0}'). "
+ "All types within a Windows Metadata file must exist in a sub namespace of the namespace that is "
+ "implied by the file name.");

public static DiagnosticDescriptor NamespacesDifferByCase = MakeRule(
"WME1067",
"CsWinRT1002",
"Namespace names cannot differ only by case",
"Multiple namespaces found with the name '{0}', namespace names cannot differ only by case.");
"Multiple namespaces found with the name '{0}'; namespace names cannot differ only by case in the Windows Runtime.");

public static DiagnosticDescriptor NoPublicTypesRule = MakeRule(
"WME1042",
"CsWinRT1003",
"No public types defined",
"Windows Runtime components must have at least one public type");

public static DiagnosticDescriptor GenericTypeRule = MakeRule(
"WME",
"CsWinRT1004",
"Class (or interface) is generic",
"Type {0} is generic. Windows Runtime types cannot be generic.");


public static DiagnosticDescriptor UnsealedClassRule = MakeRule(
"WME",
"CsWinRT1005",
"Class is unsealed",
"Exporting unsealed types is not supported. Please mark type {0} as sealed.");
"Exporting unsealed types is not supported in CsWinRT. Please mark type {0} as sealed.");

public static DiagnosticDescriptor UnsupportedTypeRule = MakeRule(
"WME",
"CsWinRT1006",
"Exposing unsupported type",
"The member '{0}' has the type '{1}' in its signature. The type '{1}' is not a valid Windows Runtime type\n"
+ "Yet, the type (or its generic parameters) implement interfaces that are valid Windows Runtime types\n"
+ "Consider changing the type '{1} in the member signature to one of the following types from System.Collections.Generic:\n{2}");
"The member '{0}' has the type '{1}' in its signature. The type '{1}' is not a valid Windows Runtime type. "
+ "Yet, the type (or its generic parameters) implement interfaces that are valid Windows Runtime types. "
+ "Consider changing the type '{1} in the member signature to one of the following types from System.Collections.Generic: {2}.");

public static DiagnosticDescriptor StructWithNoFieldsRule = MakeRule(
"WME1060",
"CsWinRT1007",
"Empty struct rule",
"Structure {0} contains no public fields. Windows Runtime structures must contain at least one public field.");

public static DiagnosticDescriptor NonWinRTInterface = MakeRule(
"WME1084",
"CsWinRT1008",
"Invalid Interface Inherited",
"Runtime component class {0} cannot implement interface {1}, as the interface is not a valid Windows Runtime interface");
"Windows Runtime component class {0} cannot implement interface {1}, as the interface is not a valid Windows Runtime interface");

public static DiagnosticDescriptor ClassConstructorRule = MakeRule(
"WME1099",
"CsWinRT1009",
"Class Constructor Rule",
"Runtime component class {0} cannot have multiple constructors of the same arity {1}");
"Classes cannot have multiple constructors of the same arity in the Windows Runtime, class {0} has multiple {1}-arity constructors");

public static DiagnosticDescriptor ParameterNamedValueRule = MakeRule(
"WME1092",
"CsWinRT1010",
"Parameter Named Value Rule",
"The method {0} has a parameter named {1} which is the same as the default return value name. "
+ "Consider using another name for the parameter or use the System.Runtime.InteropServices.WindowsRuntime.ReturnValueNameAttribute "
+ "to explicitly specify the name of the return value.");
"The parameter name {1} in method {0} is the same as the return value parameter name "
+ "used in the generated C#/WinRT interop; use a different parameter name.");

public static DiagnosticDescriptor StructHasPrivateFieldRule = MakeRule(
"WME1060(b)",
"CsWinRT1011",
"Private field in struct",
"Structure {0} has non-public field. All fields must be public for Windows Runtime structures.");

public static DiagnosticDescriptor StructHasConstFieldRule = MakeRule(
"WME1060(b)",
"CsWinRT1012",
"Const field in struct",
"Structure {0} has const field. Constants can only appear on Windows Runtime enumerations.");

public static DiagnosticDescriptor StructHasInvalidFieldRule = MakeRule(
"WME1060",
"CsWinRT1013",
"Invalid field in struct",
"Structure {0} has field of type {1}; {1} is not a valid Windows Runtime field type. Each field "
+ "in a Windows Runtime structure can only be UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Boolean, String, Enum, or itself a structure.");

public static DiagnosticDescriptor OperatorOverloadedRule = MakeRule(
"WME1087",
"CsWinRT1014",
"Operator overload exposed",
"{0} is an operator overload. Managed types cannot expose operator overloads in the Windows Runtime");

public static DiagnosticDescriptor MultipleDefaultOverloadAttribute = MakeRule(
"WME1059",
"CsWinRT1015",
"Only one overload should be designated default",
"In class {2}: Multiple {0}-parameter overloads of '{1}' are decorated with Windows.Foundation.Metadata.DefaultOverloadAttribute. The attribute may only be applied to one overload of the method.");
"In class {2}: Multiple {0}-parameter overloads of '{1}' are decorated with Windows.Foundation.Metadata.DefaultOverloadAttribute. "
+ "The attribute may only be applied to one overload of the method.");

public static DiagnosticDescriptor NeedDefaultOverloadAttribute = MakeRule(
"WME1085",
"CsWinRT1016",
"Multiple overloads seen, one needs a default", // todo better msg
"In class {2}: The {0}-parameter overloads of {1} must have exactly one method specified as the default overload by decorating it with Windows.Foundation.Metadata.DefaultOverloadAttribute.");
"In class {2}: The {0}-parameter overloads of {1} must have exactly one method specified as the default "
+ "overload by decorating it with Windows.Foundation.Metadata.DefaultOverloadAttribute.");

public static DiagnosticDescriptor JaggedArrayRule = MakeRule(
"WME1036",
"CsWinRT1017",
"Array signature found with jagged array, which is not a valid WinRT type",
"Method {0} has a nested array of type {1} in its signature. Arrays in Windows Runtime method signature cannot be nested.");

public static DiagnosticDescriptor MultiDimensionalArrayRule = MakeRule(
"WME1035",
"Array signature found with multi-dimensional array, which is not a valid WinRT type",
"CsWinRT1018",
"Array signature found with multi-dimensional array, which is not a valid Windows Runtime type",
"Method '{0}' has a multi-dimensional array of type '{1}' in its signature. Arrays in Windows Runtime method signatures must be one dimensional.");

public static DiagnosticDescriptor ArraySignature_SystemArrayRule = MakeRule(
"WME1034",
"CsWinRT1019",
"Array signature found with System.Array instance, which is not a valid WinRT type",
"In type {0}: the method {1} has signature that contains a System.Array instance; SystemArray is not a valid Windows Runtime type. Try using a different type like IList");
"In type {0}: the method {1} has signature that contains a System.Array instance; SystemArray is not "
+ "a valid Windows Runtime type. Try using a different type like IList");

public static DiagnosticDescriptor RefParameterFound = MakeRule(
"WME",
"CsWinRT1020",
"Parameter passed by reference",
"Method '{0}' has parameter '{1}' marked `ref`. Reference parameters are not allowed in Windows Runtime.");

public static DiagnosticDescriptor ArrayMarkedInOrOut = MakeRule(
"WME1103",
"CsWinRT1021",
"Array parameter marked InAttribute or OutAttribute",
"Method '{0}' has parameter '{1}' which is an array, and which has either a "
+ "System.Runtime.InteropServices.InAttribute or a System.Runtime.InteropServices.OutAttribute. "
Expand All @@ -144,7 +145,7 @@ private static DiagnosticDescriptor MakeRule(string id, string title, string mes
+ "Runtime attribute if necessary.");

public static DiagnosticDescriptor NonArrayMarkedInOrOut = MakeRule(
"WME1105",
"CsWinRT1022",
"Parameter (not array type) marked InAttribute or OutAttribute",
"Method '{0}' has parameter '{1}' with a System.Runtime.InteropServices.InAttribute "
+ "or System.Runtime.InteropServices.OutAttribute.Windows Runtime does not support "
Expand All @@ -154,29 +155,29 @@ private static DiagnosticDescriptor MakeRule(string id, string title, string mes
+ "System.Runtime.InteropServices.OutAttribute with 'out' modifier instead.");

public static DiagnosticDescriptor ArrayParamMarkedBoth = MakeRule(
"WME1101",
"CsWinRT1023",
"Array paramter marked both ReadOnlyArray and WriteOnlyArray",
"Method '{0}' has parameter '{1}' which is an array, and which has both ReadOnlyArray and WriteOnlyArray. "
+ "In the Windows Runtime, the contents array parameters must be either readable "
+ "or writable.Please remove one of the attributes from '{1}'.");

public static DiagnosticDescriptor ArrayOutputParamMarkedRead = MakeRule(
"WME1102",
"CsWinRT1024",
"Array parameter marked `out` and ReadOnlyArray",
"Method '{0}' has an output parameter '{1}' which is an array, but which has ReadOnlyArray attribute. In the Windows Runtime, "
+ "the contents of output arrays are writable.Please remove the attribute from '{1}'.");

public static DiagnosticDescriptor ArrayParamNotMarked = MakeRule(
"WME1106",
"CsWinRT1025",
"Array parameter not marked ReadOnlyArray or WriteOnlyArray way",
"Method '{0}' has parameter '{1}' which is an array. In the Windows Runtime, the "
+ "contents of array parameters must be either readable or writable.Please apply either ReadOnlyArray or WriteOnlyArray to '{1}'.");

public static DiagnosticDescriptor NonArrayMarked = MakeRule(
"WME1104",
"CsWinRT1026",
"Non-array parameter marked with ReadOnlyArray or WriteOnlyArray",
"Method '{0}' has parameter '{1}' which is not an array, and which has either a "
+ "ReadOnlyArray attribute or a WriteOnlyArray attribute . Windows Runtime does "
+ "ReadOnlyArray attribute or a WriteOnlyArray attribute. Windows Runtime does "
+ "not support marking non-array parameters with ReadOnlyArray or WriteOnlyArray.");
}
}
}
}
Loading