|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Diagnostics;
using System.Reflection;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
/*
* Define the different access levels that symbols can have.
*/
internal enum ACCESS
{
ACC_UNKNOWN, // Not yet determined.
ACC_PRIVATE,
ACC_INTERNAL_AND_PROTECTED,
ACC_INTERNAL,
ACC_PROTECTED,
ACC_INTERNALPROTECTED, // internal OR protected
ACC_PUBLIC
}
// The kinds of aggregates.
internal enum AggKindEnum
{
Unknown,
Class,
Delegate,
Interface,
Struct,
Enum,
Lim
}
/////////////////////////////////////////////////////////////////////////////////
// Special constraints.
[Flags]
internal enum SpecCons
{
None = 0x00,
New = 0x01,
Ref = 0x02,
Val = 0x04
}
// ----------------------------------------------------------------------------
//
// Symbol - the base symbol.
//
// ----------------------------------------------------------------------------
internal abstract class Symbol
{
private SYMKIND _kind; // the symbol kind
private ACCESS _access; // access level
// If this is true, then we had an error the first time so do not give an error the second time.
public Name name; // name of the symbol
public ParentSymbol parent; // parent of the symbol
public Symbol nextChild; // next child of this parent
public Symbol nextSameName; // next child of this parent with same name.
public Symbol LookupNext(symbmask_t kindmask)
{
// Keep traversing the list of symbols with same name and parent.
for (Symbol sym = nextSameName; sym != null; sym = sym.nextSameName)
{
if ((kindmask & sym.mask()) != 0)
{
return sym;
}
}
return null;
}
public ACCESS GetAccess()
{
Debug.Assert(_access != ACCESS.ACC_UNKNOWN);
return _access;
}
public void SetAccess(ACCESS access)
{
_access = access;
}
public SYMKIND getKind()
{
return _kind;
}
public void setKind(SYMKIND kind)
{
_kind = kind;
}
public symbmask_t mask()
{
return (symbmask_t)(1 << (int)_kind);
}
public CType getType()
{
if (this is MethodOrPropertySymbol methProp)
{
return methProp.RetType;
}
if (this is FieldSymbol field)
{
return field.GetType();
}
if (this is EventSymbol ev)
{
return ev.type;
}
return null;
}
public bool isStatic
{
get
{
if (this is FieldSymbol fieldInfo)
{
return fieldInfo.isStatic;
}
if (this is EventSymbol ev)
{
return ev.isStatic;
}
if (this is MethodOrPropertySymbol methProp)
{
return methProp.isStatic;
}
return this is AggregateSymbol;
}
}
private Assembly GetAssembly()
{
switch (_kind)
{
case SYMKIND.SK_MethodSymbol:
case SYMKIND.SK_PropertySymbol:
case SYMKIND.SK_FieldSymbol:
case SYMKIND.SK_EventSymbol:
case SYMKIND.SK_TypeParameterSymbol:
return ((AggregateSymbol)parent).AssociatedAssembly;
case SYMKIND.SK_AggregateSymbol:
return ((AggregateSymbol)this).AssociatedAssembly;
default:
// Should never call this with any other kind.
Debug.Fail("GetAssemblyID called on bad sym kind");
return null;
}
}
/*
* returns the assembly id for the declaration of this symbol
*/
private bool InternalsVisibleTo(Assembly assembly)
{
switch (_kind)
{
case SYMKIND.SK_MethodSymbol:
case SYMKIND.SK_PropertySymbol:
case SYMKIND.SK_FieldSymbol:
case SYMKIND.SK_EventSymbol:
case SYMKIND.SK_TypeParameterSymbol:
return ((AggregateSymbol)parent).InternalsVisibleTo(assembly);
case SYMKIND.SK_AggregateSymbol:
return ((AggregateSymbol)this).InternalsVisibleTo(assembly);
default:
// Should never call this with any other kind.
Debug.Fail("InternalsVisibleTo called on bad sym kind");
return false;
}
}
public bool SameAssemOrFriend(Symbol sym)
{
Assembly assem = GetAssembly();
return assem == sym.GetAssembly() || sym.InternalsVisibleTo(assem);
}
public bool IsOverride()
{
switch (_kind)
{
case SYMKIND.SK_MethodSymbol:
case SYMKIND.SK_PropertySymbol:
return ((MethodOrPropertySymbol)this).isOverride;
case SYMKIND.SK_EventSymbol:
return ((EventSymbol)this).isOverride;
default:
return false;
}
}
public bool IsHideByName()
{
switch (_kind)
{
case SYMKIND.SK_MethodSymbol:
case SYMKIND.SK_PropertySymbol:
return ((MethodOrPropertySymbol)this).isHideByName;
case SYMKIND.SK_EventSymbol:
MethodSymbol methAdd = ((EventSymbol)this).methAdd;
return methAdd != null && methAdd.isHideByName;
default:
return true;
}
}
/*
* returns true if this symbol is a normal symbol visible to the user
*/
public bool isUserCallable()
{
return !(this is MethodSymbol methSym) || methSym.isUserCallable();
}
}
}
|