File: CodeModel\CodeTypeRef.cs
Web Access
Project: src\src\VisualStudio\Core\Impl\Microsoft.VisualStudio.LanguageServices.Implementation.csproj (Microsoft.VisualStudio.LanguageServices.Implementation)
// 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
 
// Breaking changes from the legacy code model.
//
// CodeType: In the legacy Visual Basic code model, this property might return null. However, in
//     Roslyn this will always return a valid CodeType.
//
// TypeKind: In the legacy Visual Basic code model, this property would return vsCMTypeRefCodeType
//     if there was a valid code type -- even if it were some well-known type with a specific type
//     kind, like System.Int32 (vsCMTypeRefInt). In Roslyn, this will return the specific type kind,
//     regardless of the CodeType property.
 
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.LanguageServices.Implementation.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel;
 
[ComVisible(true)]
[ComDefaultInterface(typeof(EnvDTE.CodeTypeRef))]
public sealed class CodeTypeRef : AbstractCodeModelObject, EnvDTE.CodeTypeRef, EnvDTE80.CodeTypeRef2
{
    internal static EnvDTE.CodeTypeRef Create(CodeModelState state, object parent, ProjectId projectId, ITypeSymbol typeSymbol)
    {
        var newElement = new CodeTypeRef(state, parent, projectId, typeSymbol);
        return (EnvDTE.CodeTypeRef)ComAggregate.CreateAggregatedObject(newElement);
    }
 
    private readonly ParentHandle<object> _parentHandle;
    private readonly ProjectId _projectId;
    private readonly SymbolKey _symbolId;
 
    private CodeTypeRef(CodeModelState state, object parent, ProjectId projectId, ITypeSymbol typeSymbol)
        : base(state)
    {
        _parentHandle = new ParentHandle<object>(parent);
        _projectId = projectId;
        _symbolId = typeSymbol.GetSymbolKey();
    }
 
    internal ITypeSymbol LookupTypeSymbol()
    {
        if (CodeModelService.ResolveSymbol(this.State.Workspace, _projectId, _symbolId) is not ITypeSymbol typeSymbol)
        {
            throw Exceptions.ThrowEFail();
        }
 
        return typeSymbol;
    }
 
    public string AsFullName
    {
        get { return CodeModelService.GetAsFullNameForCodeTypeRef(LookupTypeSymbol()); }
    }
 
    public string AsString
    {
        get { return CodeModelService.GetAsStringForCodeTypeRef(LookupTypeSymbol()); }
    }
 
    public EnvDTE.CodeType CodeType
    {
        get { return (EnvDTE.CodeType)CodeModelService.CreateCodeType(this.State, _projectId, LookupTypeSymbol()); }
        set { throw Exceptions.ThrowENotImpl(); }
    }
 
    public EnvDTE.CodeTypeRef CreateArrayType(int rank)
    {
        var project = Workspace.CurrentSolution.GetProject(_projectId);
        if (project == null)
        {
            throw Exceptions.ThrowEFail();
        }
 
        var arrayType = project.GetCompilationAsync().Result.CreateArrayTypeSymbol(LookupTypeSymbol(), rank);
        return CodeTypeRef.Create(this.State, null, _projectId, arrayType);
    }
 
    public EnvDTE.CodeTypeRef ElementType
    {
        get
        {
            var typeSymbol = LookupTypeSymbol();
            if (typeSymbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array)
            {
                return CodeTypeRef.Create(this.State, this, _projectId, ((IArrayTypeSymbol)typeSymbol).ElementType);
            }
            else if (typeSymbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Pointer)
            {
                return CodeTypeRef.Create(this.State, this, _projectId, ((IPointerTypeSymbol)typeSymbol).PointedAtType);
            }
            else
            {
                throw Exceptions.ThrowEFail();
            }
        }
 
        set
        {
            throw Exceptions.ThrowENotImpl();
        }
    }
 
    public bool IsGeneric
    {
        get
        {
            return LookupTypeSymbol() is INamedTypeSymbol namedTypeSymbol
                && namedTypeSymbol.GetAllTypeArguments().Any();
        }
    }
 
    public object Parent
    {
        get { return _parentHandle.Value; }
    }
 
    public int Rank
    {
        get
        {
            var typeSymbol = LookupTypeSymbol();
            if (typeSymbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array)
            {
                return ((IArrayTypeSymbol)typeSymbol).Rank;
            }
 
            throw Exceptions.ThrowEFail();
        }
 
        set
        {
            throw new NotImplementedException();
        }
    }
 
    public EnvDTE.vsCMTypeRef TypeKind
    {
        get { return CodeModelService.GetTypeKindForCodeTypeRef(LookupTypeSymbol()); }
    }
}