diff --git a/modules/mono/build_scripts/build_assemblies.py b/modules/mono/build_scripts/build_assemblies.py index 580f51c9731..90a517cc40d 100755 --- a/modules/mono/build_scripts/build_assemblies.py +++ b/modules/mono/build_scripts/build_assemblies.py @@ -316,9 +316,35 @@ def generate_sdk_package_versions(): f.write(props) 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): - # Generate SdkPackageVersions.props + # Generate SdkPackageVersions.props and VersionDocsUrl constant generate_sdk_package_versions() # Godot API diff --git a/modules/mono/editor/Godot.NET.Sdk/.gitignore b/modules/mono/editor/Godot.NET.Sdk/.gitignore new file mode 100644 index 00000000000..55ec4bcc64a --- /dev/null +++ b/modules/mono/editor/Godot.NET.Sdk/.gitignore @@ -0,0 +1,2 @@ +# Generated sources directories +Godot.SourceGenerators/Generated diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs index 72614dd7e07..df350915969 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs @@ -5,8 +5,10 @@ using Microsoft.CodeAnalysis.Diagnostics; 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( GeneratorExecutionContext context, ClassDeclarationSyntax cds, INamedTypeSymbol symbol @@ -14,9 +16,9 @@ namespace Godot.SourceGenerators { string message = "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."; context.ReportDiagnostic(Diagnostic.Create( @@ -26,7 +28,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0001")), cds.GetLocation(), cds.SyntaxTree.FilePath)); } @@ -46,9 +49,9 @@ namespace Godot.SourceGenerators string message = $"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."; context.ReportDiagnostic(Diagnostic.Create( @@ -58,7 +61,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0002")), outerTypeDeclSyntax.GetLocation(), outerTypeDeclSyntax.SyntaxTree.FilePath)); } @@ -85,7 +89,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0101")), location, location?.SourceTree?.FilePath)); } @@ -111,7 +116,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0102")), location, location?.SourceTree?.FilePath)); } @@ -139,7 +145,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD1003")), location, location?.SourceTree?.FilePath)); } @@ -163,7 +170,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0104")), location, location?.SourceTree?.FilePath)); } @@ -189,7 +197,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0105")), location, location?.SourceTree?.FilePath)); } @@ -215,7 +224,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0106")), location, location?.SourceTree?.FilePath)); } @@ -240,7 +250,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0201")), location, location?.SourceTree?.FilePath)); } @@ -264,7 +275,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0202")), location, location?.SourceTree?.FilePath)); } @@ -288,7 +300,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0203")), location, location?.SourceTree?.FilePath)); } @@ -300,7 +313,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, 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( SyntaxNodeAnalysisContext context, @@ -319,7 +333,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0301")), typeArgumentSyntax.GetLocation(), typeArgumentSyntax.SyntaxTree.FilePath)); } @@ -331,7 +346,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, 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( SyntaxNodeAnalysisContext context, @@ -349,7 +365,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0302")), typeArgumentSyntax.GetLocation(), typeArgumentSyntax.SyntaxTree.FilePath)); } @@ -361,7 +378,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, 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( SyntaxNodeAnalysisContext context, @@ -380,7 +398,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0303")), typeArgumentSyntax.GetLocation(), typeArgumentSyntax.SyntaxTree.FilePath)); } @@ -388,11 +407,12 @@ namespace Godot.SourceGenerators public static readonly DiagnosticDescriptor GlobalClassMustDeriveFromGodotObjectRule = new DiagnosticDescriptor(id: "GD0401", 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", DiagnosticSeverity.Error, 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( SyntaxNodeAnalysisContext context, @@ -410,7 +430,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0401")), classSyntax.GetLocation(), classSyntax.SyntaxTree.FilePath)); } @@ -422,7 +443,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, 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( SyntaxNodeAnalysisContext context, @@ -440,7 +462,8 @@ namespace Godot.SourceGenerators category: "Usage", DiagnosticSeverity.Error, isEnabledByDefault: true, - description), + description, + helpLinkUri: string.Format(_helpLinkFormat, "GD0402")), classSyntax.GetLocation(), classSyntax.SyntaxTree.FilePath)); }