Skip to content

Don't load generators that target net framework explicitly.#47100

Merged
chsienki merged 4 commits intodotnet:masterfrom
chsienki:sg_no_framework
Aug 28, 2020
Merged

Don't load generators that target net framework explicitly.#47100
chsienki merged 4 commits intodotnet:masterfrom
chsienki:sg_no_framework

Conversation

@chsienki
Copy link
Copy Markdown
Member

Issue a diagnostic and don't load generator if it has references to mscorlib

@chsienki chsienki requested a review from a team as a code owner August 24, 2020 21:55
if (reference.Name?.Equals("mscorlib", StringComparison.OrdinalIgnoreCase) == true)
{
var publicKeyToken = reference.GetPublicKeyToken();
if (publicKeyToken is object && BitConverter.ToString(publicKeyToken).Equals(ExpectedPublicKey, StringComparison.OrdinalIgnoreCase))
Copy link
Copy Markdown
Member Author

@chsienki chsienki Aug 24, 2020

Choose a reason for hiding this comment

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

@jaredpar Not sure who else to ask. Does this seem like a sensible way to check for mscorlib references? (Or do we have a utility that does it in the code already?)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rather than checking for mscorlib references I would look at the TargetFrameworkAttribute on the assembly. If the moniker begins with .NETFRamework when we should reject.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ok, and we're ok that you can create .NET Framework referencing assemblies without a TargetFrameworkAttribute? A default csc.exe Generator.cs invocation will target framework, but not add the attribute.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes. Any check here is imprecise. The majority case is that they use our build infra,n not the raw compiler, which will add this attribute.

@chsienki
Copy link
Copy Markdown
Member Author

@dotnet/roslyn-compiler for a fairly small review please :)


var builder = ImmutableArray.CreateBuilder<ISourceGenerator>();
reference.AddGenerators(builder, LanguageNames.CSharp);
var analyzers = builder.ToImmutable();
Copy link
Copy Markdown
Contributor

@cston cston Aug 25, 2020

Choose a reason for hiding this comment

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

var analyzers = builder.ToImmutable(); [](start = 16, length = 38)

The statement appears to be unused. Should we Assert.Equal(1, analyzers.Length)? #Closed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Honestly, that was just left over from copy paste, but it seems sensible to assert that we did actually load a generator, so will add.


Debug.Assert(type != null);

// check if this references net framework, and issue a diagnostic if we don't allow that
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// check if this references net framework, and issue a diagnostic if we don't allow that
// check if this references net framework, and issue a diagnostic that this isn't supported

// check if this references net framework, and issue a diagnostic if we don't allow that
if (!_allowNetFramework)
{
var targetFrameworkAttribute = analyzerAssembly.GetCustomAttribute<TargetFrameworkAttribute>();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

GetCustomAttribute<T> will throw when dealing with invalid metadata (basically multiple copies of TargetFarmeworkAttribute even though it has AllowMultiple = false). Looked around a bit and seems like we are okay with this type of invalid IL breaking the compiler though. So think we can leave as is.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I did look at the source code to see how it handled those cases and it seems to just take the first one, rather than throwing?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The comment I saw said it threw. Either way though, seems like there is lots of precedenc for this.

Mostyl I commented because it took me ten minutes to figure out where this call was coming from. I wanted to write something down to make me feel better about all the time I spent looking into it.

<comment>'SourceText' is not localizable.</comment>
</data>
<data name="TypeReferencesNetFramework" xml:space="preserve">
<value>The type '{0}' references .NET Framework, which is not supported.</value>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This isn't about the type though, it's about the assembly. I would phrase it as

The assembly containing type '{0}' ...

public static byte[] NetStandardGenerator => ResourceLoader.GetOrCreateResource(ref s_netStandardGenerator, "Generators.NetStandardGenerator.dll");

private static byte[] s_noTargetGenerator;
public static byte[] NoTargetGenerator => ResourceLoader.GetOrCreateResource(ref s_noTargetGenerator, "Generators.NoTargetGenerator.dll");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rather than checking in DLLs, which continue to inflate our repo size, why not just build them as a part of the tests that need them?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah yeah didn't think of that, plus now we're not actually dealing with references this is much simpler to do.


_diagnosticAnalyzers = new Extensions<DiagnosticAnalyzer>(this, IsDiagnosticAnalyzerAttribute, GetDiagnosticsAnalyzerSupportedLanguages);
_generators = new Extensions<ISourceGenerator>(this, IsGeneratorAttribute, GetGeneratorsSupportedLanguages);
_diagnosticAnalyzers = new Extensions<DiagnosticAnalyzer>(this, IsDiagnosticAnalyzerAttribute, GetDiagnosticsAnalyzerSupportedLanguages, allowNetFramework: true);
Copy link
Copy Markdown
Contributor

@cston cston Aug 25, 2020

Choose a reason for hiding this comment

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

allowNetFramework: true [](start = 149, length = 23)

Why are analyzers allowed to target .NET Framework but generators are not? #Closed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

They were never supported, we just failed to enforce that fact. Now the fact that we didn't enforce is one of the hurdles for us movign fully to .NET Core. This change is an attempt to not make the same mistake, and create the same hurdle, for source generators,

- Remove test resources and create generators on the fly
- Reword some text
<ProjectReference Include="..\..\..\Test\Utilities\Portable\Roslyn.Test.Utilities.csproj" />
<ProjectReference Include="..\..\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj" />
<ProjectReference Include="..\..\Test\Resources\Core\Microsoft.CodeAnalysis.Compiler.Test.Resources.csproj" />
<ProjectReference Include="..\..\Test\Utilities\CSharp\Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj" />
Copy link
Copy Markdown
Contributor

@cston cston Aug 26, 2020

Choose a reason for hiding this comment

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

....\Test\Utilities\CSharp\Microsoft.CodeAnalysis.CSharp.Test.Utilities.csproj [](start = 31, length = 79)

Do we need this project reference? If it's just to create a CSharpCompilation, we should use new CSharpCompilation(...) directly instead. #Closed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah, yeah that was why I added it. I originally started by calling CSharpCompilation directly, but it was proving tricky to get all the references right. I'll switch back to that way of doing it.

@chsienki chsienki merged commit f72a248 into dotnet:master Aug 28, 2020
@ghost ghost added this to the Next milestone Aug 28, 2020
@chsienki chsienki deleted the sg_no_framework branch August 28, 2020 05:22
333fred added a commit to 333fred/roslyn that referenced this pull request Aug 28, 2020
* upstream/master: (220 commits)
  Don't load generators that target net framework explicitly. (dotnet#47100)
  Update src/Features/Core/Portable/UnifiedSuggestions/UnifiedSuggestedActionsSource.cs
  Clean up redundant code action filtering
  Remove IActiveStatementSpanTracker (dotnet#46826)
  Disable API analysis if telemetry is disabled
  Update src/Workspaces/Remote/ServiceHub/Services/CodeAnalysis/CodeAnalysisService_SemanticClassificationCache.cs
  Doc
  Compress two values.
  PR feedback
  Revert
  Revert
  Lint
  Fix formatting
  Fire and forget
  Fix mangling
  Ensure that local functions are also marked as invalid if their containing methods are generic.
  Fix dependency graph for AnalyzerRunner
  Add AnalyzerRunner target for net5.0
  Make VerifyForwardedTypes asynchronous
  Fix bug when "End statement" is used in single-line if (dotnet#47062)
  ...
@allisonchou allisonchou modified the milestones: Next, 16.8.P3 Aug 31, 2020
@chsienki chsienki restored the sg_no_framework branch April 1, 2021 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants