Example #1
0
        private bool IsTypeAccessible(ITypeNode type)
        {
            // type not declared --> treat it as accessible
            if (type == null)
            {
                return(true);
            }

            // predefined types are always accessible
            if (type.IsPredefinedType())
            {
                return(true);
            }

            // descend into ParenthesizedType
            if (type.Kind == TypeScript.Net.Types.SyntaxKind.ParenthesizedType)
            {
                return(IsTypeAccessible(type.Cast <IParenthesizedTypeNode>().Type));
            }

            // an array type is accessible iff its element type is accessible
            if (type.Kind == TypeScript.Net.Types.SyntaxKind.ArrayType)
            {
                return(IsTypeAccessible(type.Cast <IArrayTypeNode>().ElementType));
            }

            // a union type is accessible iff all its types are accessible
            if (type.Kind == TypeScript.Net.Types.SyntaxKind.UnionType)
            {
                return(type.Cast <IUnionOrIntersectionTypeNode>().Types.All(t => IsTypeAccessible(t)));
            }

            // a function type is accessible iff its return type and its type parameters are accessible
            if (type.Kind == TypeScript.Net.Types.SyntaxKind.FunctionType)
            {
                var fnType       = type.Cast <IFunctionOrConstructorTypeNode>();
                var fnParameters = fnType.Parameters ?? NodeArray.Empty <IParameterDeclaration>();
                return
                    (IsTypeAccessible(fnType.Type) &&
                     fnParameters.All(tp => IsTypeAccessible(tp.Type)));
            }

            // a type literal is accessible iff all its members are accessible
            if (type.Kind == TypeScript.Net.Types.SyntaxKind.TypeLiteral)
            {
                return(type.Cast <ITypeLiteralNode>().Members.All(m => IsMemberAccessible(m)));

                bool IsMemberAccessible(ITypeElement e)
                {
                    var memberTypes = e.Kind == TypeScript.Net.Types.SyntaxKind.PropertySignature
                        ? new[] { e.Cast <IPropertySignature>().Type }
                        : null; // handle other kinds if needed

                    return(memberTypes != null && memberTypes.All(t => IsTypeAccessible(t)));
                }
            }

            // if any type argument is inaccessible, this type is not accessible either
            var typeArguments = type.GetTypeArguments();

            if (!typeArguments.All(t => IsTypeAccessible(t)))
            {
                return(false);
            }

            // if this type couldn't be resolved, treat it as inaccessible
            var resolvedSymbol = type.ResolvedSymbol;

            if (resolvedSymbol == null)
            {
                return(false);
            }

            // otherwise, a type is accessible if any of its declarations is either explicitly exported or defined in the prelude
            return(resolvedSymbol
                   .GetDeclarations()
                   .Any(d =>
                        d.IsExported() ||
                        m_semanticModel.TypeChecker.IsPreludeDeclaration(d)));
        }