diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 278b8326da138..85670a039b6bd 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -3260,7 +3260,9 @@ private BoundNode BindSimpleProgramCompilationUnit(CompilationUnitSyntax compila } } - return FinishBindBlockParts(compilationUnit, boundStatements.ToImmutableAndFree(), diagnostics); + return new BoundNonConstructorMethodBody(compilationUnit, + FinishBindBlockParts(compilationUnit, boundStatements.ToImmutableAndFree(), diagnostics).MakeCompilerGenerated(), + expressionBody: null); } private BoundNode BindConstructorBody(ConstructorDeclarationSyntax constructor, DiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 54c10b3220ea9..da0468cefad01 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6067,4 +6067,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Top-level statements must precede namespace and type declarations. + + Cannot specify /main if there is a compilation unit with top-level statements. + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index 4dd089d69735e..2adf7117fce0b 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -1546,17 +1546,10 @@ internal bool DeclaresTheObjectClass EntryPoint? entryPoint = null; MethodSymbol? simpleProgramEntryPointSymbol = SimpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoint(this); - if (this.Options.MainTypeName != null) + if (this.Options.MainTypeName != null && !this.Options.MainTypeName.IsValidClrTypeName()) { - if (simpleProgramEntryPointSymbol is object) - { - // PROTOTYPE(SimplePrograms): Report an error that MainTypeName shouldn't be specified - } - else if (!this.Options.MainTypeName.IsValidClrTypeName()) - { - Debug.Assert(!this.Options.Errors.IsDefaultOrEmpty); - entryPoint = new EntryPoint(null, ImmutableArray.Empty); - } + Debug.Assert(!this.Options.Errors.IsDefaultOrEmpty); + entryPoint = new EntryPoint(null, ImmutableArray.Empty); } if (entryPoint is null) @@ -1566,6 +1559,13 @@ internal bool DeclaresTheObjectClass entryPoint = new EntryPoint(entryPointMethod, diagnostics); } + if (this.Options.MainTypeName != null && simpleProgramEntryPointSymbol is object) + { + var diagnostics = DiagnosticBag.GetInstance(); + diagnostics.Add(ErrorCode.ERR_SimpleProgramDisallowsMainType, NoLocation.Singleton); + entryPoint = new EntryPoint(entryPoint.MethodSymbol, entryPoint.Diagnostics.Concat(diagnostics.ToReadOnlyAndFree())); + } + Interlocked.CompareExchange(ref _lazyEntryPoint, entryPoint, null); } @@ -1585,7 +1585,7 @@ internal bool DeclaresTheObjectClass NamespaceSymbol globalNamespace = this.SourceModule.GlobalNamespace; var scriptClass = this.ScriptClass; - if (simpleProgramEntryPointSymbol is null && mainTypeName != null) + if (mainTypeName != null) { // Global code is the entry point, ignore all other Mains. if (scriptClass is object) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index b4460e24619f1..3d141ed8ea3be 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1776,6 +1776,7 @@ internal enum ErrorCode ERR_SimpleProgramLocalIsReferencedOutsideOfTopLevelStatement = 9000, ERR_SimpleProgramMultipleUnitsWithTopLevelStatements = 9001, ERR_TopLevelStatementAfterNamespaceOrType = 9002, + ERR_SimpleProgramDisallowsMainType = 9003, // Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd) } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 38ed8ec573e88..cd46f70d9043a 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -2088,6 +2088,7 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // All modifiers that might start an expression are processed above. this.ParseModifiers(modifiers, forAccessors: false); bool haveModifiers = (modifiers.Count > 0); + MemberDeclarationSyntax result; // Check for constructor form if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken && this.PeekToken(1).Kind == SyntaxKind.OpenParenToken) @@ -2100,7 +2101,7 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind // missing ';' // // Unless modifiers or attributes are present this is more likely to be a method call than a method definition. - if ((haveAttributes && IsScript) || haveModifiers) + if (haveAttributes || haveModifiers) { var token = SyntaxFactory.MissingToken(SyntaxKind.VoidKeyword); token = this.AddError(token, ErrorCode.ERR_MemberNeedsType); @@ -2108,16 +2109,23 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind var identifier = this.EatToken(); - // PROTOTYPE(SimplePrograms): Should we parse this as a local function for Simple Programs in some scenarios? - return this.ParseMethodDeclaration(attributes, modifiers, voidType, explicitInterfaceOpt: null, identifier: identifier, typeParameterList: null); + if (!IsScript) + { + if (tryParseLocalDeclarationStatementFromStartPoint(attributes, ref afterAttributesPoint, out result)) + { + return result; + } + } + else + { + return this.ParseMethodDeclaration(attributes, modifiers, voidType, explicitInterfaceOpt: null, identifier: identifier, typeParameterList: null); + } } } // Destructors are disallowed in global code, skipping check for them. // TODO: better error messages for script - MemberDeclarationSyntax result; - // Check for constant if (this.CurrentToken.Kind == SyntaxKind.ConstKeyword) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SimpleProgramNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SimpleProgramNamedTypeSymbol.cs index 7e6ab3868a5b7..e1fd37a1e2c8f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SimpleProgramNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SimpleProgramNamedTypeSymbol.cs @@ -87,7 +87,7 @@ protected override Location GetCorrespondingBaseListLocation(NamedTypeSymbol @ba } internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics - => this.DeclaringCompilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Object); // PROTOTYPE(SimplePrograms): Test with missing Object type. + => this.DeclaringCompilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Object); protected override void CheckBase(DiagnosticBag diagnostics) { @@ -95,7 +95,7 @@ protected override void CheckBase(DiagnosticBag diagnostics) var info = this.DeclaringCompilation.GetSpecialType(SpecialType.System_Object).GetUseSiteDiagnostic(); if (info != null) { - Symbol.ReportUseSiteDiagnostic(info, diagnostics, Locations[0]); + Symbol.ReportUseSiteDiagnostic(info, diagnostics, NoLocation.Singleton); } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs index 7552e4f864561..53ffa7851c9b0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/SynthesizedSimpleProgramEntryPointSymbol.cs @@ -36,12 +36,10 @@ internal SynthesizedSimpleProgramEntryPointSymbol(SimpleProgramNamedTypeSymbol c if (hasAwait) { - // PROTOTYPE(SimplePrograms): Test with missing Task type. _returnType = Binder.GetWellKnownType(containingType.DeclaringCompilation, WellKnownType.System_Threading_Tasks_Task, diagnostics, NoLocation.Singleton); } else { - // PROTOTYPE(SimplePrograms): Test with missing Void type. _returnType = Binder.GetSpecialType(containingType.DeclaringCompilation, SpecialType.System_Void, NoLocation.Singleton, diagnostics); } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 17260e4458571..c3350abcc8508 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -437,6 +437,11 @@ Cílový modul runtime nepodporuje pro člena rozhraní přístupnost na úrovni Protected, Protected internal nebo Private protected. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index f76007a5e54d1..c48e614abff38 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -437,6 +437,11 @@ Die Zugriffsoptionen "protected", "protected internal" oder "private protected" werden von der Zielruntime für einen Member einer Schnittstelle nicht unterstützt. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index b532b18f54ba1..968b65a05a76c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -437,6 +437,11 @@ El entorno de ejecución de destino no admite la accesibilidad protegida, protegida interna o protegida privada para un miembro de una interfaz. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 6ea553b844a31..df269213d32c1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -437,6 +437,11 @@ Le runtime cible ne prend pas en charge l'accessibilité 'protected', 'protected internal' ou 'private protected' d'un membre d'interface. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index c8e42d65d317a..40bdbb229f087 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -437,6 +437,11 @@ Il runtime di destinazione non supporta l'accessibilità 'protected', 'protected internal' o 'private protected' per un membro di un'interfaccia. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 06b321d02b3aa..d5b3e1f99ade4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -437,6 +437,11 @@ ターゲット ランタイムは、インターフェイスのメンバーに対して 'protected'、'protected internal'、'private protected' アクセシビリティをサポートしていません。 + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 67b4316ea9654..3173e39601462 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -437,6 +437,11 @@ 대상 런타임이 인터페이스 멤버의 'protected', 'protected internal' 또는 'private protected' 접근성을 지원하지 않습니다. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 4e81689c10a3a..0a120339107c7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -437,6 +437,11 @@ Docelowe środowisko uruchomieniowe nie obsługuje specyfikatorów dostępu „protected”, „protected internal” i „private protected” dla składowej interfejsu. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index a8631d9b143fc..243ac2dfc9e12 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -437,6 +437,11 @@ O runtime de destino não é compatível com a acessibilidade 'protected', 'protected internal' ou 'private protected' para um membro de uma interface. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index f17a1a27e9d34..3fba5b9bc0e57 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -437,6 +437,11 @@ Целевая среда выполнения не поддерживает специальные возможности "защищенный", "внутренний защищенный" или "частный защищенный" для члена интерфейса. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 54024ab3db765..387a990b13c05 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -437,6 +437,11 @@ Hedef çalışma zamanı, bir arabirim üyesi için 'protected', 'protected internal' veya 'private protected' erişilebilirliğini desteklemez. + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 850d0764bf8c6..bb466a8db0228 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -437,6 +437,11 @@ 目标运行时不支持对接口的成员使用 "protected"、"protected internal" 或 "private protected" 辅助功能。 + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index a3db41f17b678..bb63ec5321beb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -437,6 +437,11 @@ 目標執行階段不支援介面成員的 'protected'、'protected internal' 或 'private protected' 存取權。 + + Cannot specify /main if there is a compilation unit with top-level statements. + Cannot specify /main if there is a compilation unit with top-level statements. + + Cannot use local variable or local function '{0}' declared in a top-level statement in this context. Cannot use local variable or local function '{0}' declared in a top-level statement in this context. diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SimpleProgramsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SimpleProgramsTests.cs index 5a3fd7a23bf4a..6ed065f327020 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SimpleProgramsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SimpleProgramsTests.cs @@ -170,32 +170,36 @@ static void verifyModel(CSharpCompilation comp, SyntaxTree tree1, bool nullableE Assert.NotNull(operation1); Assert.IsAssignableFrom(operation1); - Assert.NotNull(ControlFlowGraph.Create((IBlockOperation)operation1.Parent.Parent)); + Assert.NotNull(ControlFlowGraph.Create((IMethodBodyOperation)((IBlockOperation)operation1.Parent.Parent).Parent)); model1.VerifyOperationTree(unit1, @" -IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: 'local(); ... iteLine(2);') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'local();') - Expression: - IInvocationOperation (void local()) (OperationKind.Invocation, Type: System.Void) (Syntax: 'local()') - Instance Receiver: - null - Arguments(0) - ILocalFunctionOperation (Symbol: void local()) (OperationKind.LocalFunction, Type: null) (Syntax: 'void local( ... iteLine(2);') - IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '=> System.C ... riteLine(2)') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'System.Cons ... riteLine(2)') +IMethodBodyOperation (OperationKind.MethodBody, Type: null) (Syntax: 'local(); ... iteLine(2);') + BlockBody: + IBlockOperation (2 statements) (OperationKind.Block, Type: null, IsImplicit) (Syntax: 'local(); ... iteLine(2);') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'local();') Expression: - IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... riteLine(2)') + IInvocationOperation (void local()) (OperationKind.Invocation, Type: System.Void) (Syntax: 'local()') Instance Receiver: null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '2') - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') - InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '=> System.C ... riteLine(2)') - ReturnedValue: - null + Arguments(0) + ILocalFunctionOperation (Symbol: void local()) (OperationKind.LocalFunction, Type: null) (Syntax: 'void local( ... iteLine(2);') + IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '=> System.C ... riteLine(2)') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'System.Cons ... riteLine(2)') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... riteLine(2)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '2') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '=> System.C ... riteLine(2)') + ReturnedValue: + null + ExpressionBody: + null "); var localDecl = unit1.DescendantNodes().OfType().Single(); var declSymbol = model1.GetDeclaredSymbol(localDecl); @@ -294,17 +298,21 @@ static void verifyModel(CSharpCompilation comp, SyntaxTree tree1, SyntaxTree tre Assert.NotNull(operation1); Assert.IsAssignableFrom(operation1); - Assert.NotNull(ControlFlowGraph.Create((IBlockOperation)operation1.Parent.Parent)); + Assert.NotNull(ControlFlowGraph.Create((IMethodBodyOperation)((IBlockOperation)operation1.Parent.Parent).Parent)); model1.VerifyOperationTree(unit1, @" -IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid) (Syntax: 'local();') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'local();') - Expression: - IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'local()') - Children(1): - IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'local') - Children(0) +IMethodBodyOperation (OperationKind.MethodBody, Type: null, IsInvalid) (Syntax: 'local();') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null, IsInvalid, IsImplicit) (Syntax: 'local();') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'local();') + Expression: + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'local()') + Children(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'local') + Children(0) + ExpressionBody: + null "); SyntaxTreeSemanticModel syntaxTreeModel = ((SyntaxTreeSemanticModel)model1); @@ -328,28 +336,32 @@ static void verifyModel(CSharpCompilation comp, SyntaxTree tree1, SyntaxTree tre Assert.NotNull(operation2); Assert.IsAssignableFrom(operation2); - Assert.NotNull(ControlFlowGraph.Create((IBlockOperation)operation2.Parent)); + Assert.NotNull(ControlFlowGraph.Create((IMethodBodyOperation)((IBlockOperation)operation2.Parent).Parent)); var isInvalid = comp.SyntaxTrees[1] == tree2 ? ", IsInvalid" : ""; model2.VerifyOperationTree(unit2, @" -IBlockOperation (1 statements) (OperationKind.Block, Type: null" + isInvalid + @") (Syntax: 'void local( ... iteLine(2);') - ILocalFunctionOperation (Symbol: void local()) (OperationKind.LocalFunction, Type: null" + isInvalid + @") (Syntax: 'void local( ... iteLine(2);') - IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '=> System.C ... riteLine(2)') - IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'System.Cons ... riteLine(2)') - Expression: - IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... riteLine(2)') - Instance Receiver: +IMethodBodyOperation (OperationKind.MethodBody, Type: null" + isInvalid + @") (Syntax: 'void local( ... iteLine(2);') + BlockBody: + IBlockOperation (1 statements) (OperationKind.Block, Type: null" + isInvalid + @", IsImplicit) (Syntax: 'void local( ... iteLine(2);') + ILocalFunctionOperation (Symbol: void local()) (OperationKind.LocalFunction, Type: null" + isInvalid + @") (Syntax: 'void local( ... iteLine(2);') + IBlockOperation (2 statements) (OperationKind.Block, Type: null) (Syntax: '=> System.C ... riteLine(2)') + IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsImplicit) (Syntax: 'System.Cons ... riteLine(2)') + Expression: + IInvocationOperation (void System.Console.WriteLine(System.Int32 value)) (OperationKind.Invocation, Type: System.Void) (Syntax: 'System.Cons ... riteLine(2)') + Instance Receiver: + null + Arguments(1): + IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '2') + ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') + InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) + IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '=> System.C ... riteLine(2)') + ReturnedValue: null - Arguments(1): - IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument, Type: null) (Syntax: '2') - ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2') - InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - IReturnOperation (OperationKind.Return, Type: null, IsImplicit) (Syntax: '=> System.C ... riteLine(2)') - ReturnedValue: - null + ExpressionBody: + null "); static void verifyModelForGlobalStatements(SyntaxTree tree1, SemanticModel model1) @@ -4399,6 +4411,68 @@ public static async Task Wait() ); } + [Fact] + public void ExplicitMain_10() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""Hi!""); + +class Program +{ + static void Main() + { + } + + static async Task Main(string[] args) + { + await Task.Factory.StartNew(() => 5); + } +} + +class Program2 +{ + static void Main(string[] args) + { + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe.WithMainTypeName("Program"), parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics( + // error CS9003: Cannot specify /main if there is a compilation unit with top-level statements. + Diagnostic(ErrorCode.ERR_SimpleProgramDisallowsMainType).WithLocation(1, 1) + ); + } + + [Fact] + public void ExplicitMain_11() + { + var text = @" +using System.Threading.Tasks; + +System.Console.Write(""Hi!""); + +class Program +{ + static void Main() + { + } +} +"; + + var comp = CreateCompilation(text, options: TestOptions.DebugExe.WithMainTypeName(""), parseOptions: DefaultParseOptions); + + comp.VerifyEmitDiagnostics( + // error CS7088: Invalid 'MainTypeName' value: ''. + Diagnostic(ErrorCode.ERR_BadCompilationOptionValue).WithArguments("MainTypeName", "").WithLocation(1, 1), + // error CS9003: Cannot specify /main if there is a compilation unit with top-level statements. + Diagnostic(ErrorCode.ERR_SimpleProgramDisallowsMainType).WithLocation(1, 1) + ); + } + [Fact] public void Yield_01() { @@ -4753,9 +4827,18 @@ public MyAttribute(int x) {} // (12,1): error CS7014: Attributes are not valid in this context. // [MyAttribute(i + 3)] Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[MyAttribute(i + 3)]").WithLocation(12, 1), - // (15,1): error CS7014: Attributes are not valid in this context. - // [MyAttribute(i + 4)] - Diagnostic(ErrorCode.ERR_AttributesNotAllowed, "[MyAttribute(i + 4)]").WithLocation(15, 1) + // (16,1): error CS0246: The type or namespace name 'local' could not be found (are you missing a using directive or an assembly reference?) + // local(); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "local").WithArguments("local").WithLocation(16, 1), + // (16,6): error CS1001: Identifier expected + // local(); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(16, 6), + // (16,6): error CS8112: Local function '()' must declare a body because it is not marked 'static extern'. + // local(); + Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "").WithArguments("()").WithLocation(16, 6), + // (19,6): warning CS8321: The local function 'local' is declared but never used + // void local() {} + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(19, 6) ); var tree1 = comp.SyntaxTrees[0]; @@ -6114,5 +6197,41 @@ private void Handle2(OperationAnalysisContext context) } } + [Fact] + public void MissingTypes_01() + { + var text = @"return;"; + + var comp = CreateEmptyCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics( + // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options. + Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1), + // error CS0518: Predefined type 'System.Object' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Object").WithLocation(1, 1), + // error CS0518: Predefined type 'System.Void' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Void").WithLocation(1, 1) + ); + } + + [Fact] + public void MissingTypes_02() + { + var text = @"await Test();"; + + var comp = CreateCompilation(text, targetFramework: TargetFramework.Minimal, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); + comp.VerifyEmitDiagnostics( + // error CS0518: Predefined type 'System.Threading.Tasks.Task' is not defined or imported + Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound).WithArguments("System.Threading.Tasks.Task").WithLocation(1, 1), + // (1,1): warning CS0028: '' has the wrong signature to be an entry point + // await Test(); + Diagnostic(ErrorCode.WRN_InvalidMainSig, "await Test();").WithArguments("").WithLocation(1, 1), + // error CS5001: Program does not contain a static 'Main' method suitable for an entry point + Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1), + // (1,7): error CS0103: The name 'Test' does not exist in the current context + // await Test(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "Test").WithArguments("Test").WithLocation(1, 7) + ); + } + } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/SimpleProgramsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/SimpleProgramsParsingTests.cs index c8f218244285b..189e6b6d04487 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/SimpleProgramsParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/SimpleProgramsParsingTests.cs @@ -2452,5 +2452,141 @@ public void Repro611177() } EOF(); } + + [Fact] + public void ConstructorLike_01() + { + var test = @"local() {}"; + + UsingTree(test, + // (1,9): error CS1002: ; expected + // local() {} + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 9) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "local"); + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ConstructorLike_02() + { + var test = @"static local() {}"; + + UsingTree(test, + // (1,13): error CS1001: Identifier expected + // static local() {} + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(1, 13) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.StaticKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "local"); + } + M(SyntaxKind.IdentifierToken); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ConstructorLike_03() + { + var test = @"[attribute] local() {}"; + + UsingTree(test, + // (1,18): error CS1001: Identifier expected + // [attribute] local() {} + Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(1, 18) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalFunctionStatement); + { + N(SyntaxKind.AttributeList); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.Attribute); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "attribute"); + } + } + N(SyntaxKind.CloseBracketToken); + } + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "local"); + } + M(SyntaxKind.IdentifierToken); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } } }