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

Diagnostics for module initializers feature #43301

Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6ebb7b0
Planned diagnostics
jnm2 Apr 12, 2020
ad85620
Accessibility diagnostics
jnm2 Apr 12, 2020
37bcdea
Signature diagnostics
jnm2 Apr 12, 2020
f6ee321
Improve readability
jnm2 Apr 12, 2020
f1f5a38
Generics diagnostics
jnm2 Apr 12, 2020
618d89a
Usages ignored without diagnostics
jnm2 Apr 12, 2020
0ae310f
Multiple application is ignored
jnm2 Apr 12, 2020
fb425a8
Couple more valid cases
jnm2 Apr 12, 2020
3153060
Diagnostic to cover the gap left by AttributeTargets.Method
jnm2 Apr 15, 2020
3255afa
Cover the gap left by AttributeTargets.Method
jnm2 Apr 15, 2020
724d23d
'Visibility' → 'Accessibility'
jnm2 Apr 30, 2020
32d8526
Group tests that vary only by keywords into theories
jnm2 Apr 30, 2020
c525661
Reserve the term 'ignored on' to indicate relying on AttributeUsage
jnm2 Apr 30, 2020
dc2ad6b
Named arguments are not relevant
jnm2 Apr 30, 2020
bdfce43
<Module> type is no longer available to VerifyIL and VerifyMemberInIL
jnm2 Apr 30, 2020
03b0c49
Fix placeholder name
jnm2 Apr 30, 2020
3f31030
Emit diagnostics should be verified
jnm2 Apr 30, 2020
22af1ab
Success cases should be executed
jnm2 May 1, 2020
b140ab9
Invalid methods should not be added as module initializers
jnm2 May 1, 2020
3328ade
Use existing helper to check accessibility
jnm2 May 1, 2020
fc412ac
Draw the line between ignored and error placements as defined by the …
jnm2 May 2, 2020
8f576b5
Mirror tests requested for mismatching AttributeTargets
jnm2 May 2, 2020
6663f90
Report additional diagnostics from accessibility check as requested
jnm2 May 2, 2020
fb488e0
Unify error messages as suggested in review, referencing WRN_MainCant…
jnm2 May 2, 2020
c36b167
Update code comments to be consistent with .resx change
jnm2 May 6, 2020
cb70fe4
Clearer message for inaccessible module initializer methods
jnm2 May 6, 2020
8212adc
Prevent false negatives when expecting a missing module initializer
jnm2 May 6, 2020
81b4d33
Make ignored constructor attribute tests more interesting
jnm2 May 6, 2020
0aba90d
Fix merge conflicts
jnm2 May 6, 2020
dc03fbe
Not accessibility tests
jnm2 May 6, 2020
a689bf4
Fix merge conflicts
jnm2 May 8, 2020
f3adf4e
Write the correct member name
jnm2 May 8, 2020
afcb701
Add tests of conditional method and attribute
jnm2 May 8, 2020
5d9c8d8
Do not emit call to method that is conditionally excluded
jnm2 May 8, 2020
64269a9
Verify that a module initializer is emitted for an extern method
jnm2 May 8, 2020
e11ff63
Use subfolder instead of partial classes
jnm2 May 9, 2020
23e81d7
Test both orders of ModuleInitializerAttribute and ConditionalAttribute
jnm2 May 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6109,4 +6109,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="IDS_FeatureModuleInitializers" xml:space="preserve">
<value>module initializers</value>
</data>
<data name="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType" xml:space="preserve">
<value>Module initializer method '{0}' must be accessible at the module level</value>
</data>
<data name="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid" xml:space="preserve">
<value>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</value>
</data>
<data name="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric" xml:space="preserve">
<value>Module initializer method '{0}' must not be generic and must not be contained in a generic type</value>
</data>
<data name="ERR_ModuleInitializerMethodMustBeOrdinary" xml:space="preserve">
<value>A module initializer must be an ordinary member method</value>
</data>
</root>
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,11 @@ internal enum ErrorCode
WRN_GivenExpressionAlwaysMatchesPattern = 8793,
WRN_IsPatternAlways = 8794,

ERR_ModuleInitializerMethodMustBeOrdinary = 8795,
ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType = 8796,
ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid = 8797,
ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric = 8798,

#endregion diagnostics introduced for C# 9.0

// Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;

Expand Down Expand Up @@ -485,8 +486,7 @@ private void DecodeWellKnownAttributeAppliedToMethod(ref DecodeWellKnownAttribut
else if (attribute.IsTargetAttribute(this, AttributeDescription.ModuleInitializerAttribute))
{
MessageID.IDS_FeatureModuleInitializers.CheckFeatureAvailability(arguments.Diagnostics, arguments.AttributeSyntaxOpt);
// PROTOTYPE(module-initializers): diagnostics
DeclaringCompilation.AddModuleInitializerMethod(this);
DecodeModuleInitializerAttribute(arguments);
}
else
{
Expand Down Expand Up @@ -763,6 +763,46 @@ private void DecodeDllImportAttribute(ref DecodeWellKnownAttributeArguments<Attr
preserveSig);
}
}

private void DecodeModuleInitializerAttribute(DecodeWellKnownAttributeArguments<AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
{
Debug.Assert(arguments.AttributeSyntaxOpt is object);

if (MethodKind != MethodKind.Ordinary)
{
arguments.Diagnostics.Add(ErrorCode.ERR_ModuleInitializerMethodMustBeOrdinary, arguments.AttributeSyntaxOpt.Location);
return;
}

Debug.Assert(ContainingType is object);
var hasError = false;

HashSet<DiagnosticInfo>? useSiteDiagnostics = null;
if (!AccessCheck.IsSymbolAccessible(this, ContainingAssembly, ref useSiteDiagnostics))
{
arguments.Diagnostics.Add(ErrorCode.ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType, arguments.AttributeSyntaxOpt.Location, Name);
hasError = true;
}

arguments.Diagnostics.Add(arguments.AttributeSyntaxOpt, useSiteDiagnostics);

if (!IsStatic || ParameterCount > 0 || !ReturnsVoid)
{
arguments.Diagnostics.Add(ErrorCode.ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid, arguments.AttributeSyntaxOpt.Location, Name);
hasError = true;
}

if (IsGenericMethod || ContainingType.IsGenericType)
{
arguments.Diagnostics.Add(ErrorCode.ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric, arguments.AttributeSyntaxOpt.Location, Name);
hasError = true;
}

if (!hasError && !CallsAreOmitted(arguments.AttributeSyntaxOpt.SyntaxTree))
{
DeclaringCompilation.AddModuleInitializerMethod(this);
}
}
#nullable restore

internal sealed override void PostDecodeWellKnownAttributes(ImmutableArray<CSharpAttributeData> boundAttributes, ImmutableArray<AttributeSyntax> allAttributeSyntaxNodes, DiagnosticBag diagnostics, AttributeLocation symbolPart, WellKnownAttributeData decodedData)
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">Chybějící vzor</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">Ve stejném adresáři nemůže být více konfiguračních souborů analyzátoru ({0}).</target>
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">Muster fehlt.</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">Dasselbe Verzeichnis ({0}) darf nicht mehrere Konfigurationsdateien des Analysetools enthalten.</target>
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">Falta un patrón.</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">No es posible que un mismo directorio ("{0}") contenga varios archivos de configuración del analizador.</target>
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">Modèle manquant</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">Plusieurs fichiers config d'analyseur ne peuvent pas figurer dans le même répertoire ('{0}').</target>
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">Criterio mancante</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">La stessa directory ('{0}') non può contenere più file di configurazione dell'analizzatore.</target>
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">パターンがありません</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">複数のアナライザー構成ファイルを同じディレクトリに入れることはできません ('{0}')。</target>
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">패턴이 없습니다.</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">분석기 구성 파일 여러 개가 동일한 디렉터리('{0}')에 있을 수 없습니다.</target>
Expand Down
20 changes: 20 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,26 @@
<target state="translated">Brak wzorca</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodAndContainingTypesMustNotBeGeneric">
<source>Module initializer method '{0}' must not be generic and must not be contained in a generic type</source>
<target state="new">Module initializer method '{0}' must not be generic and must not be contained in a generic type</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeAccessibleOutsideTopLevelType">
<source>Module initializer method '{0}' must be accessible at the module level</source>
<target state="new">Module initializer method '{0}' must be accessible at the module level</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeOrdinary">
<source>A module initializer must be an ordinary member method</source>
<target state="new">A module initializer must be an ordinary member method</target>
<note />
</trans-unit>
<trans-unit id="ERR_ModuleInitializerMethodMustBeStaticParameterlessVoid">
<source>Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</source>
<target state="new">Module initializer method '{0}' must be static, must have no parameters, and must return 'void'</target>
<note />
</trans-unit>
<trans-unit id="ERR_MultipleAnalyzerConfigsInSameDir">
<source>Multiple analyzer config files cannot be in the same directory ('{0}').</source>
<target state="translated">Wiele plików konfiguracji analizatora nie może znajdować się w tym samym katalogu („{0}”).</target>
Expand Down
Loading