Emit SDK-derived assembly attributes from the G# SDK - #2817
Merged
Conversation
Microsoft.NET.GenerateAssemblyInfo.targets gates CoreGenerateAssemblyInfo on Language being C# or VB, so a .gsproj silently lost AssemblyTitle, AssemblyProduct, AssemblyCompany and AssemblyConfiguration. ADR-0143 section D already assigns reproducing those to the G# SDK; only the emit step was missing. WriteCodeFragment cannot be reused because it is CodeDom-based and only knows C# and VB, so render the same @(AssemblyAttribute) item group as file-level G# @assembly: annotations instead, honoring MSBuild's positional, named and _IsLiteral metadata conventions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@(AssemblyAttribute)as file-level G#@assembly:annotations from a newWriteGsharpAssemblyInfoTask$(GeneratedAssemblyInfoFile)into@(Compile)beforeCoreCompile, keyed off the SDK's own inputs cache for incrementalityProblem
Microsoft.NET.GenerateAssemblyInfo.targets:189gatesCoreGenerateAssemblyInfoon'$(Language)'=='VB' or '$(Language)'=='C#'.build/Gsharp.NET.Sdk.props:4sets<Language>Gsharp</Language>, so the target silently no-ops and every.gsprojshipped an assembly with noAssemblyTitle,AssemblyProduct,AssemblyCompanyorAssemblyConfiguration.@(AssemblyAttribute)was already populated correctly by the standardGetAssemblyAttributestarget — only the emit step was missing.This violated ADR-0143 §D, which makes reproducing those attributes the G# SDK's job precisely because cs2gs deliberately drops the SDK-generated
AssemblyInfo.csand preserves only the project properties.It surfaced in the migrated Oahu app, whose window title and header rendered as "Oahu.Foundation" instead of "Oahu":
With no
AssemblyTitleAttributeon the entry assembly,ApplEnvfell through toGetExecutingAssembly()— which isOahu.Foundation.dll, becauseApplEnvlives there. The?? "Oahu"guard never fired becauseAssemblyTitlewas non-null.Approach
WriteCodeFragmentcannot be reused here: it is CodeDom-based and only emits C# and VB. Routing a generated.csAssemblyInfo through_GsharpPartitionForeignCompile+ gsgen back-translation does not work either —GeneratedDocTranslatordrops compilation-unit-level[assembly: ...]lists and emits nothing at all for a type-free file (filed as #2815).So the task renders the attributes as G# directly. It honors the same item metadata conventions
WriteCodeFragmentdefines — positional_Parameter1…_ParameterN, any other metadata as a named argument (name: valueper ADR-0080), and a<name>_IsLiteralsibling for raw code — so a project that already hand-authors<AssemblyAttribute>items for a C# build keeps working unchanged after migration.String escaping is G#-specific rather than inherited from C#: every G# interpreted string interpolates
$ident/${expr}, so a literal$is escaped as$$(docs/lexical.md).$(GeneratedAssemblyInfoFile)needs no override — the SDK already defaults it to$(IntermediateOutputPath)$(MSBuildProjectName).AssemblyInfo$(DefaultLanguageSourceExtension)andSdk.propssets that extension to.gs.Testing
dotnet test test/Sdk.Tests/Sdk.Tests.csproj— 57 passeddotnet test tools/cs2gs/Cs2Gs.Tests/Cs2Gs.Tests.csproj— 1765 passede2etests/*.shsuites pass (sdk,gsgen,foreign-cs,nuget-pack,projectref,packageref,property,multitarget,multifile,debug-info,templates)Verified end to end against the reported symptom with a G# app named
Oahureferencing the realOahu.Foundation.dll:Values round-trip through
MetadataLoadContextwith escaping intact (Probe $Company\Sub,My Probe "Title"), multi-parameter attributes (AssemblyMetadata) andInternalsVisibleToare emitted correctly, a no-op rebuild does not rewrite the file, and changing<AssemblyTitle>regenerates it and reaches the emitted assembly.Follow-ups
[assembly:]attributes and emits nothing for type-free files.EmitFriendAssemblyAnnotationsnow double-emitsInternalsVisibleTothat came from MSBuild items, since the SDK reproduces those. Benign (AllowMultiple = true) and left as-is here becauseMigrationPipelineTests.L2_Translate_PreservesInternalsVisibleTopins the current behavior.Closes #2814