| File: Symbols\Retargeting\RetargetingPropertySymbol.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting { internal sealed class RetargetingPropertySymbol : WrappedPropertySymbol { /// <summary> /// Owning RetargetingModuleSymbol. /// </summary> private readonly RetargetingModuleSymbol _retargetingModule; //we want to compute this lazily since it may be expensive for the underlying symbol private ImmutableArray<PropertySymbol> _lazyExplicitInterfaceImplementations; private ImmutableArray<ParameterSymbol> _lazyParameters; private ImmutableArray<CustomModifier> _lazyRefCustomModifiers; /// <summary> /// Retargeted custom attributes /// </summary> private ImmutableArray<CSharpAttributeData> _lazyCustomAttributes; private CachedUseSiteInfo<AssemblySymbol> _lazyCachedUseSiteInfo = CachedUseSiteInfo<AssemblySymbol>.Uninitialized; private TypeWithAnnotations.Boxed _lazyType; public RetargetingPropertySymbol(RetargetingModuleSymbol retargetingModule, PropertySymbol underlyingProperty) : base(underlyingProperty) { Debug.Assert((object)retargetingModule != null); Debug.Assert(!(underlyingProperty is RetargetingPropertySymbol)); _retargetingModule = retargetingModule; } private RetargetingModuleSymbol.RetargetingSymbolTranslator RetargetingTranslator { get { return _retargetingModule.RetargetingTranslator; } } public RetargetingModuleSymbol RetargetingModule { get { return _retargetingModule; } } public override TypeWithAnnotations TypeWithAnnotations { get { if (_lazyType is null) { var type = this.RetargetingTranslator.Retarget(_underlyingProperty.TypeWithAnnotations, RetargetOptions.RetargetPrimitiveTypesByTypeCode); if (type.Type.TryAsDynamicIfNoPia(this.ContainingType, out TypeSymbol asDynamic)) { type = TypeWithAnnotations.Create(asDynamic); } Interlocked.CompareExchange(ref _lazyType, new TypeWithAnnotations.Boxed(type), null); } return _lazyType.Value; } } public override ImmutableArray<CustomModifier> RefCustomModifiers { get { return RetargetingTranslator.RetargetModifiers(_underlyingProperty.RefCustomModifiers, ref _lazyRefCustomModifiers); } } public override ImmutableArray<ParameterSymbol> Parameters { get { if (_lazyParameters.IsDefault) { ImmutableInterlocked.InterlockedCompareExchange(ref _lazyParameters, this.RetargetParameters(), default(ImmutableArray<ParameterSymbol>)); } return _lazyParameters; } } private ImmutableArray<ParameterSymbol> RetargetParameters() { var list = _underlyingProperty.Parameters; int count = list.Length; if (count == 0) { return ImmutableArray<ParameterSymbol>.Empty; } else { ParameterSymbol[] parameters = new ParameterSymbol[count]; for (int i = 0; i < count; i++) { parameters[i] = new RetargetingPropertyParameterSymbol(this, list[i]); } return parameters.AsImmutableOrNull(); } } public override MethodSymbol GetMethod { get { return (object)_underlyingProperty.GetMethod == null ? null : this.RetargetingTranslator.Retarget(_underlyingProperty.GetMethod); } } public override MethodSymbol SetMethod { get { return (object)_underlyingProperty.SetMethod == null ? null : this.RetargetingTranslator.Retarget(_underlyingProperty.SetMethod); } } internal override bool IsExplicitInterfaceImplementation { get { return _underlyingProperty.IsExplicitInterfaceImplementation; } } public override ImmutableArray<PropertySymbol> ExplicitInterfaceImplementations { get { if (_lazyExplicitInterfaceImplementations.IsDefault) { ImmutableInterlocked.InterlockedCompareExchange( ref _lazyExplicitInterfaceImplementations, this.RetargetExplicitInterfaceImplementations(), default(ImmutableArray<PropertySymbol>)); } return _lazyExplicitInterfaceImplementations; } } private ImmutableArray<PropertySymbol> RetargetExplicitInterfaceImplementations() { var impls = _underlyingProperty.ExplicitInterfaceImplementations; if (impls.IsEmpty) { Debug.Assert(!impls.IsDefault); return impls; } // CONSIDER: we could skip the builder until the first time we see a different method after retargeting var builder = ArrayBuilder<PropertySymbol>.GetInstance(); for (int i = 0; i < impls.Length; i++) { var retargeted = this.RetargetingTranslator.Retarget(impls[i], MemberSignatureComparer.RetargetedExplicitImplementationComparer); if ((object)retargeted != null) { builder.Add(retargeted); } } return builder.ToImmutableAndFree(); } public override Symbol ContainingSymbol { get { return this.RetargetingTranslator.Retarget(_underlyingProperty.ContainingSymbol); } } public override AssemblySymbol ContainingAssembly { get { return _retargetingModule.ContainingAssembly; } } internal override ModuleSymbol ContainingModule { get { return _retargetingModule; } } public override ImmutableArray<CSharpAttributeData> GetAttributes() { return this.RetargetingTranslator.GetRetargetedAttributes(_underlyingProperty.GetAttributes(), ref _lazyCustomAttributes); } internal override IEnumerable<CSharpAttributeData> GetCustomAttributesToEmit(PEModuleBuilder moduleBuilder) { return this.RetargetingTranslator.RetargetAttributes(_underlyingProperty.GetCustomAttributesToEmit(moduleBuilder)); } internal override CallerUnsafeMode GetCallerUnsafeMode(ConsList<FieldSymbol> fieldsBeingBound) => _underlyingProperty.GetCallerUnsafeMode(fieldsBeingBound); internal override bool MustCallMethodsDirectly { get { return _underlyingProperty.MustCallMethodsDirectly; } } internal override UseSiteInfo<AssemblySymbol> GetUseSiteInfo() { AssemblySymbol primaryDependency = PrimaryDependency; if (!_lazyCachedUseSiteInfo.IsInitialized) { var result = new UseSiteInfo<AssemblySymbol>(primaryDependency); CalculateUseSiteDiagnostic(ref result); _lazyCachedUseSiteInfo.Initialize(primaryDependency, result); } return _lazyCachedUseSiteInfo.ToUseSiteInfo(primaryDependency); } internal sealed override CSharpCompilation DeclaringCompilation // perf, not correctness { get { return null; } } } }