diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index a79912f6737ede578816473793a9b212dd8394d1..d3f530654119e9c49c111f9ca0996f8a3f79bd04 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -58,6 +58,9 @@ public sealed partial class CSharpCompilation : Compilation private readonly Lazy _globalNamespaceAlias; // alias symbol used to resolve "global::". private readonly Lazy _scriptClass; + // The type of host object model if available. + private TypeSymbol? _lazyHostObjectTypeSymbol; + // All imports (using directives and extern aliases) in syntax trees in this compilation. // NOTE: We need to de-dup since the Imports objects that populate the list may be GC'd // and re-created. @@ -1461,8 +1464,8 @@ private static CSDiagnosticInfo CreateReflectionTypeNotFoundError(Type type) ); } - // The type of host object model if available. - private TypeSymbol? _lazyHostObjectTypeSymbol; + protected override ITypeSymbol? CommonScriptGlobalsType + => GetHostObjectTypeSymbol()?.GetPublicSymbol(); internal TypeSymbol? GetHostObjectTypeSymbol() { diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.cs index fdd5d79b187e20f902a03083098df00ebeb9008a..94562e0f60fc959110c29c6f8bc53ad61675c267 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.cs @@ -367,9 +367,22 @@ private bool ShouldVisitNamespace(ISymbol containingSymbol) private bool IncludeNamedType(INamedTypeSymbol namedType) { - return - namedType != null && - (!namedType.IsScriptClass || format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.IncludeScriptType)); + if (namedType is null) + { + return false; + } + + if (namedType.IsScriptClass && !format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.IncludeScriptType)) + { + return false; + } + + if (namedType == semanticModelOpt?.Compilation.ScriptGlobalsType) + { + return false; + } + + return true; } private static bool IsEnumMember(ISymbol symbol) diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index 62f4e1922d183e01c4a2506bff2852682107a5cd..f3e9e6793322fe583382b8dafff5c0977f0fa1d1 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -2530,6 +2530,199 @@ class C2 {} } } } } SymbolDisplayPartKind.NamespaceName); } + public class ScriptGlobals + { + public void Method(int p) { Event.Invoke(); } + public delegate void MyDelegate(int x); + public int Field; + public int Property => 1; + public event Action Event; + + public class NestedType + { + public void Method(int p) { Event.Invoke(); } + public delegate void MyDelegate(int x); + public int Field; + public int Property => 1; + public event Action Event; + } + } + + [Fact] + public void TestMembersInScriptGlobals() + { + var text = @"1"; + var tree = SyntaxFactory.ParseSyntaxTree(text, TestOptions.Script); + var hostReference = MetadataReference.CreateFromFile(typeof(ScriptGlobals).Assembly.Location); + + var comp = CSharpCompilation.CreateScriptCompilation( + "submission1", + tree, + TargetFrameworkUtil.GetReferences(TargetFramework.Standard).Concat(hostReference), + returnType: typeof(object), + globalsType: typeof(ScriptGlobals)); + + var model = comp.GetSemanticModel(tree); + var hostTypeSymbol = comp.GetHostObjectTypeSymbol(); + + var methodSymbol = hostTypeSymbol.GetMember("Method"); + var delegateSymbol = hostTypeSymbol.GetMember("MyDelegate"); + var fieldSymbol = hostTypeSymbol.GetMember("Field"); + var propertySymbol = hostTypeSymbol.GetMember("Property"); + var eventSymbol = hostTypeSymbol.GetMember("Event"); + + var nestedTypeSymbol = (TypeSymbol)hostTypeSymbol.GetMember("NestedType"); + var nestedMethodSymbol = nestedTypeSymbol.GetMember("Method"); + var nestedDelegateSymbol = nestedTypeSymbol.GetMember("MyDelegate"); + var nestedFieldSymbol = nestedTypeSymbol.GetMember("Field"); + var nestedPropertySymbol = nestedTypeSymbol.GetMember("Property"); + var nestedEventSymbol = nestedTypeSymbol.GetMember("Event"); + + Verify(methodSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "void Method(int p)", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation); + + Verify(delegateSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "MyDelegate(int x)", + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation); + + Verify(fieldSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "int Field", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.FieldName); + + Verify(propertySymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "int Property { get; }", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.PropertyName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation); + + Verify(eventSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "event System.Action Event", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.EventName); + + Verify(nestedTypeSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "NestedType", + SymbolDisplayPartKind.ClassName); + + Verify(nestedMethodSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "void NestedType.Method(int p)", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation); + + Verify(nestedDelegateSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "NestedType.MyDelegate(int x)", + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation); + + Verify(nestedFieldSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "int NestedType.Field", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.FieldName); + + Verify(nestedPropertySymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "int NestedType.Property { get; }", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.PropertyName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation); + + Verify(nestedEventSymbol.ToMinimalDisplayParts(model, position: 0, s_memberSignatureDisplayFormat), + "event System.Action NestedType.Event", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.NamespaceName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.EventName); + } + + private static readonly SymbolDisplayFormat s_memberSignatureDisplayFormat = + new SymbolDisplayFormat( + globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, + genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters | SymbolDisplayGenericsOptions.IncludeTypeConstraints, + memberOptions: + SymbolDisplayMemberOptions.IncludeRef | + SymbolDisplayMemberOptions.IncludeType | + SymbolDisplayMemberOptions.IncludeParameters | + SymbolDisplayMemberOptions.IncludeContainingType, + delegateStyle: + SymbolDisplayDelegateStyle.NameAndSignature, + kindOptions: + SymbolDisplayKindOptions.IncludeMemberKeyword, + propertyStyle: + SymbolDisplayPropertyStyle.ShowReadWriteDescriptor, + parameterOptions: + SymbolDisplayParameterOptions.IncludeName | + SymbolDisplayParameterOptions.IncludeType | + SymbolDisplayParameterOptions.IncludeParamsRefOut | + SymbolDisplayParameterOptions.IncludeExtensionThis | + SymbolDisplayParameterOptions.IncludeDefaultValue | + SymbolDisplayParameterOptions.IncludeOptionalBrackets, + localOptions: + SymbolDisplayLocalOptions.IncludeRef | + SymbolDisplayLocalOptions.IncludeType, + miscellaneousOptions: + SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers | + SymbolDisplayMiscellaneousOptions.UseSpecialTypes | + SymbolDisplayMiscellaneousOptions.UseErrorTypeSymbolName | + SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier | + SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral); + [Fact] public void TestRemoveAttributeSuffix1() { diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs index f598d5885a87b14366b8263802f52dbb623eb90b..42d025e25decd1642f1ec8bcc59e5f76392e6c68 100644 --- a/src/Compilers/Core/Portable/Compilation/Compilation.cs +++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs @@ -856,6 +856,12 @@ public INamedTypeSymbol GetSpecialType(SpecialType specialType) public ITypeSymbol DynamicType { get { return CommonDynamicType; } } protected abstract ITypeSymbol CommonDynamicType { get; } + /// + /// A symbol representing the script globals type. + /// + internal ITypeSymbol? ScriptGlobalsType => CommonScriptGlobalsType; + protected abstract ITypeSymbol? CommonScriptGlobalsType { get; } + /// /// A symbol representing the implicit Script class. This is null if the class is not /// defined in the compilation. diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb index e64aedb5f3b92c88e568e59021e14fcb68169b56..d2578c7523686d4f3d724866665c02c76f06d39c 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb @@ -804,6 +804,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Nothing) End Function + Protected Overrides ReadOnly Property CommonScriptGlobalsType As ITypeSymbol + Get + Return Nothing + End Get + End Property + #End Region #Region "Syntax Trees"