Merge pull request #80489 from raulsntos/dotnet/diagnostics

C#: Improve diagnostic messages and add help link
This commit is contained in:
Rémi Verschelde 2023-10-17 23:59:17 +02:00
commit ca09afd530
No known key found for this signature in database
GPG Key ID: C3336907360768E1
3 changed files with 79 additions and 28 deletions

View File

@ -316,9 +316,35 @@ def generate_sdk_package_versions():
f.write(props) f.write(props)
f.close() f.close()
# Also write the versioned docs URL to a constant for the Source Generators.
constants = """namespace Godot.SourceGenerators
{{
partial class Common
{{
public const string VersionDocsUrl = "https://docs.godotengine.org/en/{docs_branch}";
}}
}}
""".format(
**version_info
)
generators_dir = os.path.join(
dirname(script_path),
"editor",
"Godot.NET.Sdk",
"Godot.SourceGenerators",
"Generated",
)
os.makedirs(generators_dir, exist_ok=True)
with open(os.path.join(generators_dir, "Common.Constants.cs"), "w") as f:
f.write(constants)
f.close()
def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, precision): def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, precision):
# Generate SdkPackageVersions.props # Generate SdkPackageVersions.props and VersionDocsUrl constant
generate_sdk_package_versions() generate_sdk_package_versions()
# Godot API # Godot API

View File

@ -0,0 +1,2 @@
# Generated sources directories
Godot.SourceGenerators/Generated

View File

@ -5,8 +5,10 @@ using Microsoft.CodeAnalysis.Diagnostics;
namespace Godot.SourceGenerators namespace Godot.SourceGenerators
{ {
public static class Common public static partial class Common
{ {
private static readonly string _helpLinkFormat = $"{VersionDocsUrl}/tutorials/scripting/c_sharp/diagnostics/{{0}}.html";
public static void ReportNonPartialGodotScriptClass( public static void ReportNonPartialGodotScriptClass(
GeneratorExecutionContext context, GeneratorExecutionContext context,
ClassDeclarationSyntax cds, INamedTypeSymbol symbol ClassDeclarationSyntax cds, INamedTypeSymbol symbol
@ -14,9 +16,9 @@ namespace Godot.SourceGenerators
{ {
string message = string message =
"Missing partial modifier on declaration of type '" + "Missing partial modifier on declaration of type '" +
$"{symbol.FullQualifiedNameOmitGlobal()}' which is a subclass of '{GodotClasses.GodotObject}'"; $"{symbol.FullQualifiedNameOmitGlobal()}' that derives from '{GodotClasses.GodotObject}'";
string description = $"{message}. Subclasses of '{GodotClasses.GodotObject}' " + string description = $"{message}. Classes that derive from '{GodotClasses.GodotObject}' " +
"must be declared with the partial modifier."; "must be declared with the partial modifier.";
context.ReportDiagnostic(Diagnostic.Create( context.ReportDiagnostic(Diagnostic.Create(
@ -26,7 +28,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0001")),
cds.GetLocation(), cds.GetLocation(),
cds.SyntaxTree.FilePath)); cds.SyntaxTree.FilePath));
} }
@ -46,9 +49,9 @@ namespace Godot.SourceGenerators
string message = string message =
$"Missing partial modifier on declaration of type '{fullQualifiedName}', " + $"Missing partial modifier on declaration of type '{fullQualifiedName}', " +
$"which contains one or more subclasses of '{GodotClasses.GodotObject}'"; $"which contains nested classes that derive from '{GodotClasses.GodotObject}'";
string description = $"{message}. Subclasses of '{GodotClasses.GodotObject}' and their " + string description = $"{message}. Classes that derive from '{GodotClasses.GodotObject}' and their " +
"containing types must be declared with the partial modifier."; "containing types must be declared with the partial modifier.";
context.ReportDiagnostic(Diagnostic.Create( context.ReportDiagnostic(Diagnostic.Create(
@ -58,7 +61,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0002")),
outerTypeDeclSyntax.GetLocation(), outerTypeDeclSyntax.GetLocation(),
outerTypeDeclSyntax.SyntaxTree.FilePath)); outerTypeDeclSyntax.SyntaxTree.FilePath));
} }
@ -85,7 +89,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0101")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -111,7 +116,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0102")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -139,7 +145,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD1003")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -163,7 +170,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0104")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -189,7 +197,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0105")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -215,7 +224,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0106")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -240,7 +250,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0201")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -264,7 +275,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0202")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -288,7 +300,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0203")),
location, location,
location?.SourceTree?.FilePath)); location?.SourceTree?.FilePath));
} }
@ -300,7 +313,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
"The generic type argument must be a Variant compatible type. Use a Variant compatible type as the generic type argument."); "The generic type argument must be a Variant compatible type. Use a Variant compatible type as the generic type argument.",
helpLinkUri: string.Format(_helpLinkFormat, "GD0301"));
public static void ReportGenericTypeArgumentMustBeVariant( public static void ReportGenericTypeArgumentMustBeVariant(
SyntaxNodeAnalysisContext context, SyntaxNodeAnalysisContext context,
@ -319,7 +333,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0301")),
typeArgumentSyntax.GetLocation(), typeArgumentSyntax.GetLocation(),
typeArgumentSyntax.SyntaxTree.FilePath)); typeArgumentSyntax.SyntaxTree.FilePath));
} }
@ -331,7 +346,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
"The generic type argument must be a Variant type. Use a Variant type as the generic type argument."); "The generic type argument must be a Variant type. Use a Variant type as the generic type argument.",
helpLinkUri: string.Format(_helpLinkFormat, "GD0302"));
public static void ReportGenericTypeParameterMustBeVariantAnnotated( public static void ReportGenericTypeParameterMustBeVariantAnnotated(
SyntaxNodeAnalysisContext context, SyntaxNodeAnalysisContext context,
@ -349,7 +365,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0302")),
typeArgumentSyntax.GetLocation(), typeArgumentSyntax.GetLocation(),
typeArgumentSyntax.SyntaxTree.FilePath)); typeArgumentSyntax.SyntaxTree.FilePath));
} }
@ -361,7 +378,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
"The generic type argument must be a Variant type. Use a Variant type as the generic type argument."); "The generic type argument must be a Variant type. Use a Variant type as the generic type argument.",
helpLinkUri: string.Format(_helpLinkFormat, "GD0303"));
public static void ReportTypeArgumentParentSymbolUnhandled( public static void ReportTypeArgumentParentSymbolUnhandled(
SyntaxNodeAnalysisContext context, SyntaxNodeAnalysisContext context,
@ -380,7 +398,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0303")),
typeArgumentSyntax.GetLocation(), typeArgumentSyntax.GetLocation(),
typeArgumentSyntax.SyntaxTree.FilePath)); typeArgumentSyntax.SyntaxTree.FilePath));
} }
@ -388,11 +407,12 @@ namespace Godot.SourceGenerators
public static readonly DiagnosticDescriptor GlobalClassMustDeriveFromGodotObjectRule = public static readonly DiagnosticDescriptor GlobalClassMustDeriveFromGodotObjectRule =
new DiagnosticDescriptor(id: "GD0401", new DiagnosticDescriptor(id: "GD0401",
title: "The class must derive from GodotObject or a derived class", title: "The class must derive from GodotObject or a derived class",
messageFormat: "The class '{0}' must derive from GodotObject or a derived class.", messageFormat: "The class '{0}' must derive from GodotObject or a derived class",
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
"The class must derive from GodotObject or a derived class. Change the base class or remove the '[GlobalClass]' attribute."); "The class must derive from GodotObject or a derived class. Change the base class or remove the '[GlobalClass]' attribute.",
helpLinkUri: string.Format(_helpLinkFormat, "GD0401"));
public static void ReportGlobalClassMustDeriveFromGodotObject( public static void ReportGlobalClassMustDeriveFromGodotObject(
SyntaxNodeAnalysisContext context, SyntaxNodeAnalysisContext context,
@ -410,7 +430,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0401")),
classSyntax.GetLocation(), classSyntax.GetLocation(),
classSyntax.SyntaxTree.FilePath)); classSyntax.SyntaxTree.FilePath));
} }
@ -422,7 +443,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
"The class must be a non-generic type. Remove the generic arguments or the '[GlobalClass]' attribute."); "The class must be a non-generic type. Remove the generic arguments or the '[GlobalClass]' attribute.",
helpLinkUri: string.Format(_helpLinkFormat, "GD0401"));
public static void ReportGlobalClassMustNotBeGeneric( public static void ReportGlobalClassMustNotBeGeneric(
SyntaxNodeAnalysisContext context, SyntaxNodeAnalysisContext context,
@ -440,7 +462,8 @@ namespace Godot.SourceGenerators
category: "Usage", category: "Usage",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true, isEnabledByDefault: true,
description), description,
helpLinkUri: string.Format(_helpLinkFormat, "GD0402")),
classSyntax.GetLocation(), classSyntax.GetLocation(),
classSyntax.SyntaxTree.FilePath)); classSyntax.SyntaxTree.FilePath));
} }