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

enable main methods to be asynchronous #18157

Merged
merged 13 commits into from
Mar 31, 2017
9 changes: 9 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -5041,4 +5041,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_VoidAssignment" xml:space="preserve">
<value>A value of type 'void' may not be assigned.</value>
</data>
<data name="IDS_FeatureAsyncMain" xml:space="preserve">
<value>async main</value>
</data>
</root>
66 changes: 34 additions & 32 deletions src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Symbols;
using static Microsoft.CodeAnalysis.CSharp.Binder;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

Expand All @@ -40,7 +41,7 @@ public sealed partial class CSharpCompilation : Compilation
// version. Do not make any changes to the public interface without making the corresponding
// change to the VB version.
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

internal static readonly ParallelOptions DefaultParallelOptions = new ParallelOptions();

Expand Down Expand Up @@ -93,9 +94,9 @@ internal Conversions Conversions
/// <summary>
/// Holds onto data related to reference binding.
/// The manager is shared among multiple compilations that we expect to have the same result of reference binding.
/// In most cases this can be determined without performing the binding. If the compilation however contains a circular
/// In most cases this can be determined without performing the binding. If the compilation however contains a circular
/// metadata reference (a metadata reference that refers back to the compilation) we need to avoid sharing of the binding results.
/// We do so by creating a new reference manager for such compilation.
/// We do so by creating a new reference manager for such compilation.
/// </summary>
private ReferenceManager _referenceManager;

Expand Down Expand Up @@ -128,7 +129,7 @@ public override bool IsCaseSensitive
}

/// <summary>
/// The options the compilation was created with.
/// The options the compilation was created with.
/// </summary>
public new CSharpCompilationOptions Options
{
Expand Down Expand Up @@ -172,14 +173,14 @@ public LanguageVersion LanguageVersion
protected override INamedTypeSymbol CommonCreateErrorTypeSymbol(INamespaceOrTypeSymbol container, string name, int arity)
{
return new ExtendedErrorTypeSymbol(
container.EnsureCSharpSymbolOrNull<INamespaceOrTypeSymbol, NamespaceOrTypeSymbol>(nameof(container)),
container.EnsureCSharpSymbolOrNull<INamespaceOrTypeSymbol, NamespaceOrTypeSymbol>(nameof(container)),
name, arity, errorInfo: null);
}

protected override INamespaceSymbol CommonCreateErrorNamespaceSymbol(INamespaceSymbol container, string name)
{
return new MissingNamespaceSymbol(
container.EnsureCSharpSymbolOrNull<INamespaceSymbol, NamespaceSymbol>(nameof(container)),
container.EnsureCSharpSymbolOrNull<INamespaceSymbol, NamespaceSymbol>(nameof(container)),
name);
}

Expand Down Expand Up @@ -408,8 +409,8 @@ private CSharpCompilation Update(
/// </summary>
public new CSharpCompilation WithAssemblyName(string assemblyName)
{
// Can't reuse references since the source assembly name changed and the referenced symbols might
// have internals-visible-to relationship with this compilation or they might had a circular reference
// Can't reuse references since the source assembly name changed and the referenced symbols might
// have internals-visible-to relationship with this compilation or they might had a circular reference
// to this compilation.

return new CSharpCompilation(
Expand All @@ -429,9 +430,9 @@ private CSharpCompilation Update(
/// Creates a new compilation with the specified references.
/// </summary>
/// <remarks>
/// The new <see cref="CSharpCompilation"/> will query the given <see cref="MetadataReference"/> for the underlying
/// metadata as soon as the are needed.
///
/// The new <see cref="CSharpCompilation"/> will query the given <see cref="MetadataReference"/> for the underlying
/// metadata as soon as the are needed.
///
/// The new compilation uses whatever metadata is currently being provided by the <see cref="MetadataReference"/>.
/// E.g. if the current compilation references a metadata file that has changed since the creation of the compilation
/// the new compilation is going to use the updated version, while the current compilation will be using the previous (it doesn't change).
Expand Down Expand Up @@ -684,7 +685,7 @@ internal override bool HasSubmissionResult()

/// <summary>
/// Creates a new compilation without the specified syntax trees. Preserves metadata info for use with trees
/// added later.
/// added later.
/// </summary>
public new CSharpCompilation RemoveSyntaxTrees(params SyntaxTree[] trees)
{
Expand All @@ -693,7 +694,7 @@ internal override bool HasSubmissionResult()

/// <summary>
/// Creates a new compilation without the specified syntax trees. Preserves metadata info for use with trees
/// added later.
/// added later.
/// </summary>
public new CSharpCompilation RemoveSyntaxTrees(IEnumerable<SyntaxTree> trees)
{
Expand Down Expand Up @@ -746,7 +747,7 @@ internal override bool HasSubmissionResult()

/// <summary>
/// Creates a new compilation without any syntax trees. Preserves metadata info
/// from this compilation for use with trees added later.
/// from this compilation for use with trees added later.
/// </summary>
public new CSharpCompilation RemoveAllSyntaxTrees()
{
Expand Down Expand Up @@ -805,7 +806,7 @@ internal override bool HasSubmissionResult()
}

// TODO(tomat): Consider comparing #r's of the old and the new tree. If they are exactly the same we could still reuse.
// This could be a perf win when editing a script file in the IDE. The services create a new compilation every keystroke
// This could be a perf win when editing a script file in the IDE. The services create a new compilation every keystroke
// that replaces the tree with a new one.
var reuseReferenceManager = !oldTree.HasReferenceOrLoadDirectives() && !newTree.HasReferenceOrLoadDirectives();
syntaxAndDeclarations = syntaxAndDeclarations.ReplaceSyntaxTree(oldTree, newTree);
Expand Down Expand Up @@ -872,7 +873,7 @@ internal IEnumerable<string> ExternAliases
/// </summary>
/// <returns><see cref="AssemblySymbol"/> or <see cref="ModuleSymbol"/> corresponding to the given reference or null if there is none.</returns>
/// <remarks>
/// Uses object identity when comparing two references.
/// Uses object identity when comparing two references.
/// </remarks>
internal new Symbol GetAssemblyOrModuleSymbol(MetadataReference reference)
{
Expand Down Expand Up @@ -976,7 +977,7 @@ public MetadataReference GetDirectiveReference(ReferenceDirectiveTriviaSyntax di
/// <summary>
/// Get all modules in this compilation, including the source module, added modules, and all
/// modules of referenced assemblies that do not come from an assembly with an extern alias.
/// Metadata imported from aliased assemblies is not visible at the source level except through
/// Metadata imported from aliased assemblies is not visible at the source level except through
/// the use of an extern alias directive. So exclude them from this list which is used to construct
/// the global namespace.
/// </summary>
Expand Down Expand Up @@ -1017,7 +1018,7 @@ internal void GetUnaliasedReferencedAssemblies(ArrayBuilder<AssemblySymbol> asse
}

/// <summary>
/// Gets the <see cref="MetadataReference"/> that corresponds to the assembly symbol.
/// Gets the <see cref="MetadataReference"/> that corresponds to the assembly symbol.
/// </summary>
public new MetadataReference GetMetadataReference(IAssemblySymbol assemblySymbol)
{
Expand Down Expand Up @@ -1065,7 +1066,7 @@ internal SourceAssemblySymbol SourceAssembly
}

/// <summary>
/// Gets the root namespace that contains all namespaces and types defined in source code or in
/// Gets the root namespace that contains all namespaces and types defined in source code or in
/// referenced metadata, merged into a single namespace hierarchy.
/// </summary>
internal new NamespaceSymbol GlobalNamespace
Expand All @@ -1075,7 +1076,7 @@ internal SourceAssemblySymbol SourceAssembly
if ((object)_lazyGlobalNamespace == null)
{
// Get the root namespace from each module, and merge them all together
// Get all modules in this compilation, ones referenced directly by the compilation
// Get all modules in this compilation, ones referenced directly by the compilation
// as well as those referenced by all referenced assemblies.

var modules = ArrayBuilder<ModuleSymbol>.GetInstance();
Expand Down Expand Up @@ -1369,7 +1370,7 @@ internal bool DeclaresTheObjectClass
internal new MethodSymbol GetEntryPoint(CancellationToken cancellationToken)
{
EntryPoint entryPoint = GetEntryPointAndDiagnostics(cancellationToken);
return entryPoint == null ? null : entryPoint.MethodSymbol;
return entryPoint?.MethodSymbol;
}

internal EntryPoint GetEntryPointAndDiagnostics(CancellationToken cancellationToken)
Expand Down Expand Up @@ -1456,9 +1457,9 @@ private MethodSymbol FindEntryPoint(CancellationToken cancellationToken, out Imm
var viableEntryPoints = ArrayBuilder<MethodSymbol>.GetInstance();
foreach (var candidate in entryPointCandidates)
{
if (!candidate.HasEntryPointSignature())
if (!candidate.HasEntryPointSignature(this))
{
// a single error for partial methods:
// a single error for partial methods
warnings.Add(ErrorCode.WRN_InvalidMainSig, candidate.Locations.First(), candidate);
continue;
}
Expand All @@ -1472,7 +1473,8 @@ private MethodSymbol FindEntryPoint(CancellationToken cancellationToken, out Imm

if (candidate.IsAsync)
{
diagnostics.Add(ErrorCode.ERR_MainCantBeAsync, candidate.Locations.First(), candidate);
// PROTOTYPE(async-main): Get the diagnostic to point to a smaller syntax piece.
CheckFeatureAvailability(candidate.DeclaringSyntaxReferences.Single().GetSyntax(), MessageID.IDS_FeatureAsyncMain, diagnostics);
}

viableEntryPoints.Add(candidate);
Expand Down Expand Up @@ -2171,8 +2173,8 @@ internal ImmutableArray<Diagnostic> GetDiagnosticsForSyntaxTree(
{
//remove some errors that don't have locations in the tree, like "no suitable main method."
//Members in trees other than the one being examined are not compiled. This includes field
//initializers which can result in 'field is never initialized' warnings for fields in partial
//types when the field is in a different source file than the one for which we're getting diagnostics.
//initializers which can result in 'field is never initialized' warnings for fields in partial
//types when the field is in a different source file than the one for which we're getting diagnostics.
//For that reason the bag must be also filtered by tree.
IEnumerable<Diagnostic> methodBodyDiagnostics = GetDiagnosticsForMethodBodiesInTree(syntaxTree, filterSpanWithinTree, cancellationToken);

Expand Down Expand Up @@ -2730,14 +2732,14 @@ protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(
return TupleTypeSymbol.Create(
locationOpt: null, // no location for the type declaration
elementTypes: typesBuilder.ToImmutableAndFree(),
elementLocations: elementLocations,
elementNames: elementNames,
elementLocations: elementLocations,
elementNames: elementNames,
compilation: this,
shouldCheckConstraints: false);
}

protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(
INamedTypeSymbol underlyingType,
INamedTypeSymbol underlyingType,
ImmutableArray<string> elementNames,
ImmutableArray<Location> elementLocations)
{
Expand All @@ -2757,7 +2759,7 @@ protected override INamedTypeSymbol CommonCreateTupleTypeSymbol(
}

protected override INamedTypeSymbol CommonCreateAnonymousTypeSymbol(
ImmutableArray<ITypeSymbol> memberTypes,
ImmutableArray<ITypeSymbol> memberTypes,
ImmutableArray<string> memberNames,
ImmutableArray<Location> memberLocations,
ImmutableArray<bool> memberIsReadOnly)
Expand Down Expand Up @@ -2855,7 +2857,7 @@ internal override int CompareSourceLocations(Location loc1, Location loc2)
#endregion

/// <summary>
/// Returns if the compilation has all of the members necessary to emit metadata about
/// Returns if the compilation has all of the members necessary to emit metadata about
/// dynamic types.
/// </summary>
/// <returns></returns>
Expand Down Expand Up @@ -2911,7 +2913,7 @@ internal bool EnableEnumArrayBlockInitialization
return sustainedLowLatency != null && sustainedLowLatency.ContainingAssembly == Assembly.CorLibrary;
}
}

internal override bool IsIOperationFeatureEnabled()
{
var options = (CSharpParseOptions)this.SyntaxTrees.FirstOrDefault()?.Options;
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ internal enum ErrorCode
ERR_VarargsAsync = 4006,
ERR_ByRefTypeAndAwait = 4007,
ERR_BadAwaitArgVoidCall = 4008,
ERR_MainCantBeAsync = 4009,
// ERR_MainCantBeAsync = 4009,
Copy link
Member

Choose a reason for hiding this comment

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

Should we delete the corresponding resource string?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

ERR_CantConvAsyncAnonFuncReturns = 4010,
ERR_BadAwaiterPattern = 4011,
ERR_BadSpecialByRefLocal = 4012,
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ internal enum MessageID
IDS_FeatureExpressionBodiedAccessor = MessageBase + 12715,
IDS_FeatureExpressionBodiedDeOrConstructor = MessageBase + 12716,
IDS_ThrowExpression = MessageBase + 12717,
IDS_FeatureAsyncMain = MessageBase + 12718,
}

// Message IDs may refer to strings that need to be localized.
Expand Down Expand Up @@ -183,6 +184,10 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
// Checks are in the LanguageParser unless otherwise noted.
switch (feature)
{
// C# 7.1 features.
case MessageID.IDS_FeatureAsyncMain:
return LanguageVersion.CSharp7_1;

// C# 7 features.
case MessageID.IDS_FeatureBinaryLiteral:
case MessageID.IDS_FeatureDigitSeparator:
Expand Down
Loading