From 5f7a42bc0322861afdb7dcc2166b26b7ab53da12 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Tue, 28 Jul 2015 15:54:38 -0700 Subject: [PATCH] Allow top-level extension methods in VB script code --- .../Symbols/NamedTypeSymbolExtensions.vb | 5 ++ .../Source/SourceMemberContainerTypeSymbol.vb | 2 +- .../Source/SourceMemberMethodSymbol.vb | 2 +- .../Symbols/Source/SourceMethodSymbol.vb | 4 +- .../ExtensionMethods/ExtensionMethodTests.vb | 53 +++++++++++++++++++ 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbolExtensions.vb b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbolExtensions.vb index 4ffa5aab8ba..f5dbba99323 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbolExtensions.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/NamedTypeSymbolExtensions.vb @@ -113,5 +113,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return False End Function + + Friend Function AllowsExtensionMethods(container As NamedTypeSymbol) As Boolean + Return container.TypeKind = TypeKind.Module OrElse container.IsScriptClass + End Function + End Module End Namespace diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb index d86d5f0d537..0c7f4fdc91b 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberContainerTypeSymbol.vb @@ -3333,7 +3333,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ' Only Modules can declare extension methods. If _lazyContainsExtensionMethods = ThreeState.Unknown Then - If Not (_containingSymbol.Kind = SymbolKind.Namespace AndAlso Me.TypeKind = TypeKind.Module AndAlso Me.AnyMemberHasAttributes) Then + If Not (_containingSymbol.Kind = SymbolKind.Namespace AndAlso Me.AllowsExtensionMethods() AndAlso Me.AnyMemberHasAttributes) Then _lazyContainsExtensionMethods = ThreeState.False End If End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb index 56eda5f9bb6..6b7e0e3e061 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMemberMethodSymbol.vb @@ -85,7 +85,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ' Check attributes quickly. _quickAttributes = binder.QuickAttributeChecker.CheckAttributes(syntax.AttributeLists) - If containingType.TypeKind <> TypeKind.Module Then + If Not containingType.AllowsExtensionMethods() Then ' Extension methods in source can only be inside modules. _quickAttributes = _quickAttributes And Not QuickAttributes.Extension End If diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb index fce98242277..a46b56cae17 100644 --- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb +++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceMethodSymbol.vb @@ -1471,7 +1471,7 @@ lReportErrorOnTwoTokens: Dim isExtensionMethod As Boolean = False If Not (Me.MethodKind <> MethodKind.Ordinary AndAlso Me.MethodKind <> MethodKind.DeclareMethod) AndAlso - m_containingType.TypeKind = TYPEKIND.Module AndAlso + m_containingType.AllowsExtensionMethods() AndAlso Me.ParameterCount <> 0 Then Debug.Assert(Me.IsShared) @@ -1569,7 +1569,7 @@ lReportErrorOnTwoTokens: If Me.MethodKind <> MethodKind.Ordinary AndAlso Me.MethodKind <> MethodKind.DeclareMethod Then arguments.Diagnostics.Add(ERRID.ERR_ExtensionOnlyAllowedOnModuleSubOrFunction, arguments.AttributeSyntaxOpt.GetLocation()) - ElseIf m_containingType.TypeKind <> TYPEKIND.Module Then + ElseIf Not m_containingType.AllowsExtensionMethods() Then arguments.Diagnostics.Add(ERRID.ERR_ExtensionMethodNotInModule, arguments.AttributeSyntaxOpt.GetLocation()) ElseIf Me.ParameterCount = 0 Then diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/ExtensionMethods/ExtensionMethodTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/ExtensionMethods/ExtensionMethodTests.vb index aa2c70a3e8c..7f8f0d1c4a4 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/ExtensionMethods/ExtensionMethodTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/ExtensionMethods/ExtensionMethodTests.vb @@ -2431,6 +2431,59 @@ End Module End Sub + + Public Sub ScriptExtensionMethods() + Dim comp = CreateCompilationWithMscorlib( + + +Shared Function F(o As Object) As Object + Return Nothing +End Function +Dim o As New Object() +o.F()]]> + , + parseOptions:=TestOptions.Script, + references:={MscorlibRef, SystemCoreRef}) + comp.VerifyDiagnostics() + Assert.True(comp.SourceAssembly.MightContainExtensionMethods) + End Sub + + + Public Sub InteractiveExtensionMethods() + Dim parseOptions = TestOptions.Interactive + Dim references = {MscorlibRef, SystemCoreRef} + Dim source0 = +Shared Function F(o As Object) As Object + Return 0 +End Function +Dim o As New Object() +? o.F()]]> + Dim source1 = +Shared Function G(o As Object) As Object + Return 1 +End Function +Dim o As New Object() +? o.G().F()]]> + Dim s0 = VisualBasicCompilation.CreateSubmission( + "s0.dll", + syntaxTree:=Parse(source0.Value, parseOptions), + references:=references) + s0.VerifyDiagnostics() + Assert.True(s0.SourceAssembly.MightContainExtensionMethods) + Dim s1 = VisualBasicCompilation.CreateSubmission( + "s1.dll", + syntaxTree:=Parse(source0.Value, parseOptions), + previousSubmission:=s0, + references:=references) + s1.VerifyDiagnostics() + Assert.True(s1.SourceAssembly.MightContainExtensionMethods) + End Sub + End Class End Namespace -- GitLab