コード例 #1
0
        internal static Type Lookup(ITypeName typeName, TypeResolutionState typeResolutionState)
        {
            Type result;

            s_cache.TryGetValue(Tuple.Create(typeName, typeResolutionState), out result);
            return(result);
        }
コード例 #2
0
 private TypeResolutionState(TypeResolutionState other, HashSet <string> typesDefined)
 {
     this.namespaces           = other.namespaces;
     this.assemblies           = other.assemblies;
     _typesDefined             = typesDefined;
     this.genericArgumentCount = other.genericArgumentCount;
     this.attribute            = other.attribute;
 }
コード例 #3
0
 internal TypeResolutionState(TypeResolutionState other, int genericArgumentCount, bool attribute)
 {
     this.namespaces           = other.namespaces;
     this.assemblies           = other.assemblies;
     _typesDefined             = other._typesDefined;
     this.genericArgumentCount = genericArgumentCount;
     this.attribute            = attribute;
 }
コード例 #4
0
        private bool VisitTypeName(TypeName typeName, int genericArgumentCount, bool isAttribute)
        {
            var classDefn = _symbolTable.LookupType(typeName);

            if (classDefn != null && classDefn.IsAmbiguous())
            {
                _parser.ReportError(typeName.Extent,
                                    nameof(ParserStrings.AmbiguousTypeReference),
                                    ParserStrings.AmbiguousTypeReference,
                                    typeName.Name,
                                    GetModuleQualifiedName(classDefn.ExternalNamespaces[0], typeName.Name),
                                    GetModuleQualifiedName(classDefn.ExternalNamespaces[1], typeName.Name));
            }
            else if (classDefn != null && genericArgumentCount == 0)
            {
                typeName.SetTypeDefinition(classDefn.Type);
            }
            else
            {
                Exception           e;
                TypeResolutionState trs = genericArgumentCount > 0 || isAttribute
                    ? new TypeResolutionState(_typeResolutionState, genericArgumentCount, isAttribute)
                    : _typeResolutionState;

                var type = TypeResolver.ResolveTypeNameWithContext(typeName, out e, null, trs);
                if (type == null)
                {
                    if (_symbolTable.GetCurrentTypeDefinitionAst() != null)
                    {
                        // [ordered] is an attribute, but it's looks like a type constraint.
                        if (!typeName.FullName.Equals(LanguagePrimitives.OrderedAttribute, StringComparison.OrdinalIgnoreCase))
                        {
                            string errorId;
                            string errorMsg;
                            if (isAttribute)
                            {
                                errorId  = nameof(ParserStrings.CustomAttributeTypeNotFound);
                                errorMsg = ParserStrings.CustomAttributeTypeNotFound;
                            }
                            else
                            {
                                errorId  = nameof(ParserStrings.TypeNotFound);
                                errorMsg = ParserStrings.TypeNotFound;
                            }

                            _parser.ReportError(typeName.Extent, errorId, errorMsg, typeName.Name);
                        }
                    }
                }
                else
                {
                    ((ISupportsTypeCaching)typeName).CachedType = type;
                    return(true);
                }
            }

            return(false);
        }
コード例 #5
0
 private SymbolResolver(Parser parser, TypeResolutionState typeResolutionState)
 {
     _symbolTable                    = new SymbolTable(parser);
     _parser                         = parser;
     _typeResolutionState            = typeResolutionState;
     _symbolResolvePostActionVisitor = new SymbolResolvePostActionVisitor {
         _symbolResolver = this
     };
 }
コード例 #6
0
        /// <summary>
        /// A helper method to call ResolveTypeNameWorker in steps.
        /// </summary>
        private static Type CallResolveTypeNameWorkerHelper(TypeName typeName,
                                                            ExecutionContext context,
                                                            IEnumerable <Assembly> assemblies,
                                                            bool isAssembliesExplicitlyPassedIn,
                                                            TypeResolutionState typeResolutionState,
                                                            out Exception exception)
        {
            if (t_searchedAssemblies == null)
            {
                t_searchedAssemblies = new HashSet <Assembly>();
            }
            else
            {
                // Clear the set before starting a full search to make sure we have a clean start.
                t_searchedAssemblies.Clear();
            }

            try
            {
                exception = null;
                var  currentScope = context != null ? context.EngineSessionState.CurrentScope : null;
                Type result       = ResolveTypeNameWorker(typeName, currentScope, typeResolutionState.assemblies, t_searchedAssemblies, typeResolutionState,
                                                          /*onlySearchInGivenAssemblies*/ false, /* reportAmbiguousException */ true, out exception);
                if (exception == null && result == null)
                {
                    if (context != null && !isAssembliesExplicitlyPassedIn)
                    {
                        // If the assemblies to search from is not specified by the caller of 'ResolveTypeNameWithContext',
                        // then we search our assembly cache first, so as to give preference to resolving the type against
                        // assemblies explicitly loaded by powershell, for example, via importing module/snapin.
                        result = ResolveTypeNameWorker(typeName, currentScope, context.AssemblyCache.Values, t_searchedAssemblies, typeResolutionState,
                                                       /*onlySearchInGivenAssemblies*/ true, /* reportAmbiguousException */ false, out exception);
                    }

                    if (result == null)
                    {
                        // Search from the assembly list passed in.
                        result = ResolveTypeNameWorker(typeName, currentScope, assemblies, t_searchedAssemblies, typeResolutionState,
                                                       /*onlySearchInGivenAssemblies*/ true, /* reportAmbiguousException */ false, out exception);
                    }
                }

                return(result);
            }
            finally
            {
                // Clear the set after a full search, so dynamic assemblies can get reclaimed as needed.
                t_searchedAssemblies.Clear();
            }
        }
コード例 #7
0
        private static Type ResolveTypeNameWorker(TypeName typeName,
                                                  SessionStateScope currentScope,
                                                  IEnumerable <Assembly> loadedAssemblies,
                                                  HashSet <Assembly> searchedAssemblies,
                                                  TypeResolutionState typeResolutionState,
                                                  bool onlySearchInGivenAssemblies,
                                                  bool reportAmbiguousException,
                                                  out Exception exception)
        {
            Type result;

            exception = null;

            if (!onlySearchInGivenAssemblies)
            {
                while (currentScope != null)
                {
                    result = currentScope.LookupType(typeName.Name);
                    if (result != null)
                    {
                        return(result);
                    }

                    currentScope = currentScope.Parent;
                }

                if (TypeAccelerators.builtinTypeAccelerators.TryGetValue(typeName.Name, out result))
                {
                    return(result);
                }
            }

            result = LookForTypeInAssemblies(typeName, loadedAssemblies, searchedAssemblies, typeResolutionState, reportAmbiguousException, out exception);
            if (exception != null)
            {
                // skip the rest of lookups, if exception reported.
                return(result);
            }

            if (!onlySearchInGivenAssemblies && result == null)
            {
                lock (TypeAccelerators.userTypeAccelerators)
                {
                    TypeAccelerators.userTypeAccelerators.TryGetValue(typeName.Name, out result);
                }
            }

            return(result);
        }
コード例 #8
0
        internal static void ResolveSymbols(Parser parser, ScriptBlockAst scriptBlockAst)
        {
            Diagnostics.Assert(scriptBlockAst.Parent == null, "Can only resolve starting from the root");

            var usingState = scriptBlockAst.UsingStatements.Count > 0
                ? new TypeResolutionState(TypeOps.GetNamespacesForTypeResolutionState(scriptBlockAst.UsingStatements), TypeResolutionState.emptyAssemblies)
                : TypeResolutionState.GetDefaultUsingState(null);
            var resolver = new SymbolResolver(parser, usingState);

            resolver._symbolTable.EnterScope(scriptBlockAst, ScopeType.ScriptBlock);
            scriptBlockAst.Visit(resolver);
            resolver._symbolTable.LeaveScope();

            Diagnostics.Assert(resolver._symbolTable._scopes.Count == 0, "Somebody missed removing a scope");
        }
コード例 #9
0
 internal static void Add(ITypeName typeName, TypeResolutionState typeResolutionState, Type type)
 {
     s_cache.GetOrAdd(Tuple.Create(typeName, typeResolutionState), type);
 }
コード例 #10
0
        private static Type LookForTypeInAssemblies(TypeName typeName,
                                                    IEnumerable <Assembly> assemblies,
                                                    HashSet <Assembly> searchedAssemblies,
                                                    TypeResolutionState typeResolutionState,
                                                    bool reportAmbiguousException,
                                                    out Exception exception)
        {
            exception = null;
            string alternateNameToFind = typeResolutionState.GetAlternateTypeName(typeName.Name);
            Type   foundType           = null;
            Type   foundType2          = null;

            foreach (Assembly assembly in assemblies)
            {
                // Skip the assemblies that we already searched and found no matching type.
                if (searchedAssemblies.Contains(assembly))
                {
                    continue;
                }

                try
                {
                    Type targetType = LookForTypeInSingleAssembly(assembly, typeName.Name);
                    if (targetType == null && alternateNameToFind != null)
                    {
                        targetType = LookForTypeInSingleAssembly(assembly, alternateNameToFind);
                    }

                    if (targetType != null)
                    {
                        if (!reportAmbiguousException)
                        {
                            // accelerator for the common case, when we are not interested in ambiguity exception.
                            return(targetType);
                        }

                        // .NET has forward notation for types, when they declared in one assembly and implemented in another one.
                        // We want to support both scenarios:
                        // 1) When we pass assembly with declared forwarded type (CoreCLR)
                        // 2) When we pass assembly with declared forwarded type and assembly with implemented forwarded type (FullCLR)
                        // In the case (2) we should not report duplicate, hence this check
                        if (foundType != targetType)
                        {
                            if (foundType != null)
                            {
                                foundType2 = targetType;
                                break;
                            }
                            else
                            {
                                foundType = targetType;
                            }
                        }
                    }
                    else
                    {
                        // We didn't find a match from the current assembly, so update the searchedAssemblies set.
                        searchedAssemblies.Add(assembly);
                    }
                }
                catch (Exception) // Assembly.GetType might throw unadvertised exceptions
                {
                }
            }

            if (foundType2 != null)
            {
                exception = new AmbiguousTypeException(typeName, new string[] { foundType.AssemblyQualifiedName, foundType2.AssemblyQualifiedName });
                return(null);
            }

            return(foundType);
        }
コード例 #11
0
        internal static Type ResolveTypeNameWithContext(TypeName typeName, out Exception exception, Assembly[] assemblies, TypeResolutionState typeResolutionState)
        {
            ExecutionContext context = null;

            exception = null;

            if (typeResolutionState == null)
            {
                // Usings from script scope (and if no script scope, fall back to default 'using namespace system')
                context             = LocalPipeline.GetExecutionContextFromTLS();
                typeResolutionState = TypeResolutionState.GetDefaultUsingState(context);
            }

            // We can do the cache lookup only if we don't define type in the current scope (cache would be invalid in this case).
            var result = typeResolutionState.ContainsTypeDefined(typeName.Name)
                ? null
                : TypeCache.Lookup(typeName, typeResolutionState);

            if (result != null)
            {
                return(result);
            }

            if (typeName.AssemblyName != null)
            {
                result = ResolveAssemblyQualifiedTypeName(typeName, out exception);
                TypeCache.Add(typeName, typeResolutionState, result);
                return(result);
            }

            // Simple typename (no generics, no arrays, no assembly name)
            // We use the following search order, using the specified name (assumed to be fully namespace qualified):
            //
            //     * Search scope table (includes 'using type x = ...' aliases)
            //     * Built in type accelerators (implicit 'using type x = ...' aliases that are effectively in global scope
            //     * typeResolutionState.assemblies, which contains:
            //          - Assemblies with PS types, added by 'using module'
            //          - Assemblies added by 'using assembly'.
            //          For this case, we REPORT ambiguity, since user explicitly specifies the set of assemblies.
            //     * All other loaded assemblies (excluding dynamic assemblies created for PS defined types).
            //          IGNORE ambiguity. It mimics PS v4. There are two reasons:
            //          1) If we report ambiguity, we need to fix our caching logic accordingly.
            //             Consider this code
            //                  Add-Type 'public class Q {}' # ok
            //                  Add-Type 'public class Q { }' # get error about the same name
            //                  [Q] # we would get error about ambiguous type, because we added assembly with duplicated type
            //                      # before we can report TYPE_ALREADY_EXISTS error.
            //
            //                  Add-Type 'public class Q2 {}' # ok
            //                  [Q2] # caching Q2 type
            //                  Add-Type 'public class Q2 { }' # get error about the same name
            //                  [Q2] # we don't get an error about ambiguous type, because it's cached already
            //          2) NuGet (VS Package Management console) uses MEF extensibility model.
            //             Different assemblies includes same interface (i.e. NuGet.VisualStudio.IVsPackageInstallerServices),
            //             where they include only methods that they are interested in the interface declaration (result interfaces are different!).
            //             Then, at runtime VS provides an instance. Everything work as far as instance has compatible API.
            //             So [NuGet.VisualStudio.IVsPackageInstallerServices] can be resolved to several different assemblies and it's ok.
            //     * User defined type accelerators (rare - interface was never public)
            //
            // If nothing is found, we search again, this time applying any 'using namespace ...' declarations including the implicit 'using namespace System'.
            // We must search all using aliases and REPORT an error if there is an ambiguity.

            // If this is TypeDefinition we should not cache anything in TypeCache.
            if (typeName._typeDefinitionAst != null)
            {
                return(typeName._typeDefinitionAst.Type);
            }

            if (context == null)
            {
                context = LocalPipeline.GetExecutionContextFromTLS();
            }

            // Use the explicitly passed-in assembly list when it's specified by the caller.
            // Otherwise, retrieve all currently loaded assemblies.
            var assemList = assemblies ?? ClrFacade.GetAssemblies(typeResolutionState, typeName);
            var isAssembliesExplicitlyPassedIn = assemblies != null;

            result = CallResolveTypeNameWorkerHelper(typeName, context, assemList, isAssembliesExplicitlyPassedIn, typeResolutionState, out exception);

            if (result != null)
            {
                TypeCache.Add(typeName, typeResolutionState, result);
                return(result);
            }

            if (exception == null)
            {
                foreach (var ns in typeResolutionState.namespaces)
                {
                    var newTypeNameToSearch = ns + "." + typeName.Name;
                    newTypeNameToSearch = typeResolutionState.GetAlternateTypeName(newTypeNameToSearch) ??
                                          newTypeNameToSearch;
                    var newTypeName = new TypeName(typeName.Extent, newTypeNameToSearch);
#if CORECLR
                    if (!isAssembliesExplicitlyPassedIn)
                    {
                        // We called 'ClrFacade.GetAssemblies' to get assemblies. That means the assemblies to search from
                        // are not pre-defined, and thus we have to refetch assembly again based on the new type name.
                        assemList = ClrFacade.GetAssemblies(typeResolutionState, newTypeName);
                    }
#endif
                    var newResult = CallResolveTypeNameWorkerHelper(newTypeName, context, assemList, isAssembliesExplicitlyPassedIn, typeResolutionState, out exception);

                    if (exception != null)
                    {
                        break;
                    }

                    if (newResult != null)
                    {
                        if (result == null)
                        {
                            result = newResult;
                        }
                        else
                        {
                            exception = new AmbiguousTypeException(typeName, new string[] { result.FullName, newResult.FullName });
                            result    = null;
                            break;
                        }
                    }
                }
            }

            if (exception != null)
            {
                // AmbiguousTypeException is for internal representation only.
                var ambiguousException = exception as AmbiguousTypeException;
                if (ambiguousException != null)
                {
                    exception = new PSInvalidCastException("AmbiguousTypeReference", exception,
                                                           ParserStrings.AmbiguousTypeReference, ambiguousException.TypeName.Name,
                                                           ambiguousException.Candidates[0], ambiguousException.Candidates[1]);
                }
            }

            if (result != null)
            {
                TypeCache.Add(typeName, typeResolutionState, result);
            }

            return(result);
        }
コード例 #12
0
        private static Type LookForTypeInAssemblies(TypeName typeName, IEnumerable <Assembly> assemblies, TypeResolutionState typeResolutionState, bool reportAmbiguousException, out Exception exception)
        {
            exception = null;
            string alternateNameToFind = typeResolutionState.GetAlternateTypeName(typeName.Name);
            Type   foundType           = null;
            Type   foundType2          = null;

            foreach (Assembly assembly in assemblies)
            {
                try
                {
                    Type targetType = LookForTypeInSingleAssembly(assembly, typeName.Name);;
                    if (targetType == null && alternateNameToFind != null)
                    {
                        targetType = LookForTypeInSingleAssembly(assembly, alternateNameToFind);
                    }

                    if (targetType != null)
                    {
                        if (!reportAmbiguousException)
                        {
                            // accelerator  for the common case, when we are not interested  in ambiguity exception.
                            return(targetType);
                        }

                        // .NET has forward notation for types, when they declared in one assembly and implemented in another one.
                        // We want to support both scenarios:
                        // 1) When we pass assembly with declared forwarded type (CoreCLR)
                        // 2) When we pass assembly with declared forwarded type and assembly with implemented forwarded type (FullCLR)
                        // In the case (2) we should not report duplicate, hence this check
                        if (foundType != targetType)
                        {
                            if (foundType != null)
                            {
                                foundType2 = targetType;
                                break;
                            }
                            else
                            {
                                foundType = targetType;
                            }
                        }
                    }
                }
                catch (Exception e) // Assembly.GetType might throw unadvertised exceptions
                {
                    CommandProcessorBase.CheckForSevereException(e);
                }
            }

            if (foundType2 != null)
            {
                exception = new AmbiguousTypeException(typeName, new String[] { foundType.AssemblyQualifiedName, foundType2.AssemblyQualifiedName });
                return(null);
            }

            return(foundType);
        }