/// <summary>
        /// Finds the details of the symbol at the given script file location.
        /// </summary>
        /// <param name="scriptFile">The ScriptFile in which the symbol can be located.</param>
        /// <param name="lineNumber">The line number at which the symbol can be located.</param>
        /// <param name="columnNumber">The column number at which the symbol can be located.</param>
        /// <returns></returns>
        public Task <SymbolDetails> FindSymbolDetailsAtLocationAsync(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            SymbolReference symbolReference =
                AstOperations.FindSymbolAtPosition(
                    scriptFile.ScriptAst,
                    lineNumber,
                    columnNumber);

            if (symbolReference == null)
            {
                return(Task.FromResult <SymbolDetails>(null));
            }

            symbolReference.FilePath = scriptFile.FilePath;
            return(SymbolDetails.CreateAsync(
                       symbolReference,
                       _runspaceContext.CurrentRunspace,
                       _executionService));
        }
        public override async Task <Hover> Handle(HoverParams request, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                _logger.LogDebug("Hover request canceled for file: {0}", request.TextDocument.Uri);
                return(null);
            }

            ScriptFile scriptFile = _workspaceService.GetFile(request.TextDocument.Uri);

            SymbolDetails symbolDetails =
                await _symbolsService.FindSymbolDetailsAtLocationAsync(
                    scriptFile,
                    request.Position.Line + 1,
                    request.Position.Character + 1).ConfigureAwait(false);

            if (symbolDetails == null)
            {
                return(null);
            }

            List <MarkedString> symbolInfo = new List <MarkedString>();

            symbolInfo.Add(new MarkedString("PowerShell", symbolDetails.DisplayString));

            if (!string.IsNullOrEmpty(symbolDetails.Documentation))
            {
                symbolInfo.Add(new MarkedString("markdown", symbolDetails.Documentation));
            }

            Range symbolRange = GetRangeFromScriptRegion(symbolDetails.SymbolReference.ScriptRegion);

            return(new Hover
            {
                Contents = new MarkedStringsOrMarkupContent(symbolInfo),
                Range = symbolRange
            });
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Finds the details of the symbol at the given script file location.
        /// </summary>
        /// <param name="scriptFile">The ScriptFile in which the symbol can be located.</param>
        /// <param name="lineNumber">The line number at which the symbol can be located.</param>
        /// <param name="columnNumber">The column number at which the symbol can be located.</param>
        /// <returns></returns>
        public async Task <SymbolDetails> FindSymbolDetailsAtLocationAsync(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            SymbolReference symbolReference =
                AstOperations.FindSymbolAtPosition(
                    scriptFile.ScriptAst,
                    lineNumber,
                    columnNumber);

            if (symbolReference == null)
            {
                return(null);
            }

            symbolReference.FilePath = scriptFile.FilePath;
            SymbolDetails symbolDetails = await SymbolDetails.CreateAsync(
                symbolReference,
                _powerShellContextService).ConfigureAwait(false);

            return(symbolDetails);
        }
Ejemplo n.º 4
0
        private int ImportPackageNodes(PackageDatabase source)
        {
            int packageNodeIndex, sourceMemberIndex, targetMemberIndex;

            sourceMemberIndex = targetMemberIndex = 0; // 0 == sentinel root
            sourceMemberIndex = source.DeclaredMembers.GetFirstChild(sourceMemberIndex);
            SymbolDetails memberDetails = source.DeclaredMemberDetails[sourceMemberIndex];

            int memberName = source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex);

            memberName        = this.StringStore.FindOrAddString(source.StringStore[memberName]);
            targetMemberIndex = this.DeclaredMembers.Add(targetMemberIndex, memberName);
            this.DeclaredMemberTypes.Add(memberDetails.Type);

            packageNodeIndex = targetMemberIndex;

            Debug.Assert(memberDetails.Type == SymbolType.Package);
            Debug.Assert(source.DeclaredMembers.GetNextSibling(sourceMemberIndex) < 0);

            // Add optional pre-release node
            if (source.Identity.ReleaseName.IsPrereleaseVersion())
            {
                int packageReleaseId = this.StringStore.FindOrAddString(source.Identity.ReleaseName);
                this.DeclaredMembers.Add(targetMemberIndex, packageReleaseId);
                this.DeclaredMemberTypes.Add(SymbolType.Version);
            }

            // Inject popularity rank as an sibling node of package contents
            int popularityRank   = source.GetPopularityRank(sourceMemberIndex);
            int popularityRankId = this.StringStore.FindOrAddString(popularityRank.ToString());

            this.DeclaredMembers.Add(targetMemberIndex, popularityRankId);
            this.DeclaredMemberTypes.Add(SymbolType.PopularityRank);

            return(packageNodeIndex);
        }
Ejemplo n.º 5
0
        private bool AddUniqueMembers(
            PackageDatabase source,
            int sourceMemberIndex,
            int targetMemberIndex,
            DatabaseAddResult result,
            ArdbVersion version)
        {
            int           pathLength              = result.CurrentPath.Length;
            SymbolDetails memberDetails           = source.DeclaredMemberDetails[sourceMemberIndex];
            bool          hasUniqueDescendants    = false;
            int           indexToAddChildrenUnder = targetMemberIndex;

            // Add public types and namespaces which contain either
            bool addMember = false;

            if (memberDetails.Type == SymbolType.FrameworkTarget)
            {
                String8 encodedFrameworkNames = source.StringStore[source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex)];
                result.CurrentFrameworkNames = new HashSet <string>(encodedFrameworkNames.ToString().ToFrameworkNames());
            }
            else if (memberDetails.Type == SymbolType.Namespace)
            {
                addMember = ContainsPublics(source, sourceMemberIndex);
            }
            else if (memberDetails.Type == SymbolType.Assembly)
            {
                if (result.CurrentFrameworkNames != null)
                {
                    result.CurrentFrameworkNames.Clear();
                }
            }
            else if (memberDetails.Type.IsType())
            {
                addMember = memberDetails.Modifiers.HasFlag(SymbolModifier.Public);
            }

            // Add the member if it is a public type or contains them [and set 'indexInTarget' to the added member]
            if (addMember)
            {
                result.PublicTypeCount++;

                // Remap name for target StringStore [all unique names will be added anyway]
                int     memberName     = source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex);
                String8 memberNameText = source.StringStore[memberName];
                result.CurrentPath.Append((result.CurrentPath.Length > 0 ? "." : "") + memberNameText.ToString());
                memberName = this.StringStore.FindOrAddString(memberNameText);

                string           fullTypeName;
                HashSet <string> frameworkTargets;

                // See if this name is already found in the merged namespace tree
                if (!this.MergedMembers.TryFindChildByName(targetMemberIndex, memberName, out indexToAddChildrenUnder))
                {
                    // If not, add it, and the tree is unique because this name is
                    indexToAddChildrenUnder = this.MergedMembers.Add(targetMemberIndex, memberName);

                    // Identify the package which added it
                    int packageNameIdentifier = this.StringStore.FindOrAddString(source.Identity.PackageName);
                    this.MergedMemberSourcePackageIdentifier.Add(packageNameIdentifier);
                    this.MergedMemberDuplicateCount.Add(1);

                    hasUniqueDescendants = true;
                    result.MergedTypeCount++;

                    if (version != ArdbVersion.V1 && memberDetails.Type.IsType())
                    {
                        // We have encountered a fully-qualified type name for the
                        // very first time. We will associate this name with the
                        // current framework target. We will also remember this
                        // sourceMemberIndex, in order to use it as the item
                        // to add when populating the ARDB.
                        fullTypeName = result.CurrentPath.ToString();
                        result.TypeToFrameworkTargetsMap.Add(fullTypeName, new HashSet <string>());

                        if (result.CurrentFrameworkNames != null)
                        {
                            result.TypeToFrameworkTargetsMap[fullTypeName].UnionWith(result.CurrentFrameworkNames);
                        }

                        result.TypeNameToTypeIndexMap.Add(fullTypeName, sourceMemberIndex);
                    }
                }
                else
                {
                    // Otherwise, if this is a duplicate with another entry in the same package, still include it (different framework targets)
                    String8 sourcePackage = this.StringStore[this.MergedMemberSourcePackageIdentifier[indexToAddChildrenUnder]];
                    if (version != ArdbVersion.V1 &&
                        result.CurrentFrameworkNames != null &&
                        sourcePackage.Equals(source.Identity.PackageName))
                    {
                        hasUniqueDescendants = true;
                        result.MergedTypeCount++;

                        if (version != ArdbVersion.V1 && memberDetails.Type.IsType())
                        {
                            // We have encountered a fully-qualified type name that we've seen
                            // before. We will record the current framework target but
                            // will already have a source member index to use to add
                            // to the ARDB later.
                            fullTypeName     = result.CurrentPath.ToString();
                            frameworkTargets = result.TypeToFrameworkTargetsMap[fullTypeName];
                            frameworkTargets.UnionWith(result.CurrentFrameworkNames);
                            Debug.Assert(result.TypeNameToTypeIndexMap.ContainsKey(fullTypeName));
                        }
                    }
                    else
                    {
                        // If this isn't unique, increment the count of copies
                        this.MergedMemberDuplicateCount[indexToAddChildrenUnder] += 1;
                    }
                }
            }

            if (!memberDetails.Type.IsType())
            {
                int childIndex = source.DeclaredMembers.GetFirstChild(sourceMemberIndex);
                while (childIndex > 0)
                {
                    hasUniqueDescendants |= AddUniqueMembers(source, childIndex, indexToAddChildrenUnder, result, version);
                    childIndex            = source.DeclaredMembers.GetNextSibling(childIndex);
                }
            }

            // Add the package which had this member to results if it wasn't unique
            if (hasUniqueDescendants == false)
            {
                result.SourcePackageNames[sourceMemberIndex] = this.StringStore[this.MergedMemberSourcePackageIdentifier[indexToAddChildrenUnder]];
            }

            // Record whether this member was unique (and added)
            result.WasMemberAdded[sourceMemberIndex] = hasUniqueDescendants;
            result.CurrentPath.Length = pathLength;
            return(hasUniqueDescendants);
        }
Ejemplo n.º 6
0
        private void ImportPublics(
            PackageDatabase source,
            int sourceMemberIndex,
            int targetMemberIndex,
            bool?[] uniqueMembers,
            ArdbVersion ardbVersion)
        {
            SymbolDetails memberDetails = source.DeclaredMemberDetails[sourceMemberIndex];

            // Skip adding any subtrees which are not unique
            if (uniqueMembers != null)
            {
                bool?wasUnique = uniqueMembers[sourceMemberIndex];
                if (wasUnique == null)
                {
                    // Not added because not a public type (or ancestor wasn't)
                    return;
                }
                else if (wasUnique == false)
                {
                    // Not added because a non-unique item was detected for a package db
                    // that is not permitted to add duplicates (only MS frameworks pkgs should).
                    return;
                }
            }

            int indexInTarget = targetMemberIndex;

            // Index everything except the sentinel root. Also skip assembly nodes,
            // as matches will occur at the package node (which will actually
            // represent either a package or a reference assembly).
            if (sourceMemberIndex > 0 && (ardbVersion != ArdbVersion.V1 || memberDetails.Type != SymbolType.FrameworkTarget))
            {
                // Remap name for target StringStore
                int memberName = source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex);
                memberName = this.StringStore.FindOrAddString(source.StringStore[memberName]);

                // Add this member if it doesn't already exist [ex: same namespaces in multiple binaries in Package]
                if (!this.DeclaredMembers.TryFindChildByName(targetMemberIndex, memberName, out indexInTarget))
                {
                    // Add member to target tree
                    indexInTarget = this.DeclaredMembers.Add(targetMemberIndex, memberName);
                    this.DeclaredMemberTypes.Add(memberDetails.Type);

                    // Validate DeclaredMembers and DeclaredMemberTypes are in sync
                    if (this.DeclaredMemberTypes.Count != this.DeclaredMembers.Count)
                    {
                        throw new InvalidOperationException(String.Format(Resources.DatabaseArraysOutOfSync, "DeclaredMemberTypes"));
                    }

                    // Add member to index [types and namespaces so 'find second-to-last value' search works]
                    this.Index.AddItem(memberName, indexInTarget);

                    if (memberDetails.Type == SymbolType.Package)
                    {
                        int addedNode;

                        // If this package is a pre-release version, we will introduce
                        // a new node that holds the specific release details. This is
                        // a short-term fix required to allow a fixer to request installation
                        // of a pre-release only package. Nuget will add a new API in the future
                        // that prevents the need for this node (which we can then remove).
                        if (source.Identity.ReleaseName.IsPrereleaseVersion())
                        {
                            int packageReleaseId = this.StringStore.FindOrAddString(source.Identity.ReleaseName);
                            addedNode = this.DeclaredMembers.Add(indexInTarget, packageReleaseId);

                            if (ardbVersion == ArdbVersion.V1)
                            {
                                // For V1, we injected the prerelease node as a parent to all
                                // following nodes. For post-V1, this node is a sibling with
                                // popularity rank.
                                indexInTarget = addedNode;
                            }

                            this.DeclaredMemberTypes.Add(SymbolType.Version);
                        }

                        // Inject popularity rank as an sibling node of package contents
                        int popularityRank   = source.GetPopularityRank(sourceMemberIndex);
                        int popularityRankId = this.StringStore.FindOrAddString(popularityRank.ToString());
                        addedNode = this.DeclaredMembers.Add(indexInTarget, popularityRankId);

                        if (ardbVersion == ArdbVersion.V1)
                        {
                            // For V1, we injected the popularity rank directly underneath the
                            // package or pre-release node. Post-V1, this node is a sibling of
                            // the target frameworks node.
                            // popularity rank.
                            indexInTarget = addedNode;
                        }

                        this.DeclaredMemberTypes.Add(SymbolType.PopularityRank);
                    }
                }
                else if (ardbVersion == ArdbVersion.V1)
                {
                    if (memberDetails.Type == SymbolType.Package)
                    {
                        // For V1, we need to skip injected popularity node and prerelease nodes
                        // when looking for duplicate children. This isn't required for post-V1, as
                        // these nodes are introduced as siblings of the TFM and/or assembly-level data.
                        indexInTarget = this.DeclaredMembers.GetFirstChild(indexInTarget);

                        SymbolType symbolType = this.GetMemberType(indexInTarget);
                        if (symbolType == SymbolType.Version)
                        {
                            indexInTarget = this.DeclaredMembers.GetFirstChild(indexInTarget);
                        }

                        // At this point, we should always have the popularity rank in hand
                        Debug.Assert(this.GetMemberType(indexInTarget) == SymbolType.PopularityRank);
                    }
                    else if (memberDetails.Type == SymbolType.FrameworkTarget)
                    {
                        // If we find a TFM node, we will skip past it;
                        indexInTarget = this.DeclaredMembers.GetFirstChild(indexInTarget);
                    }
                }
            }

            // Recurse on children down to type level. We do not walk type members.
            // This means that we will exclude public nested types from the database.
            if (!memberDetails.Type.IsType())
            {
                int childIndex = source.DeclaredMembers.GetFirstChild(sourceMemberIndex);
                while (childIndex > 0)
                {
                    ImportPublics(source, childIndex, indexInTarget, uniqueMembers, ardbVersion);
                    childIndex = source.DeclaredMembers.GetNextSibling(childIndex);
                }
            }
        }
Ejemplo n.º 7
0
        private void ImportFrameworkTargets(PackageDatabase source, int packageMemberIndex, DatabaseAddResult databaseAddResult)
        {
            Dictionary <string, HashSet <int> > frameworkTargetsToIncludedTypes = new Dictionary <string, HashSet <int> >();
            HashSet <int> frameworkTargetTypes;

            foreach (string type in Sorted(databaseAddResult.TypeToFrameworkTargetsMap.Keys))
            {
                HashSet <string> frameworkTargetsSet = databaseAddResult.TypeToFrameworkTargetsMap[type];
                string[]         frameworkTargets    = new string[frameworkTargetsSet.Count];
                frameworkTargetsSet.CopyTo(frameworkTargets, 0);
                Array.Sort(frameworkTargets);

                string sortedFrameworkTargets = StringExtensions.EncodeFrameworkNamesToXml(frameworkTargets);

                if (!frameworkTargetsToIncludedTypes.TryGetValue(sortedFrameworkTargets, out frameworkTargetTypes))
                {
                    frameworkTargetTypes = frameworkTargetsToIncludedTypes[sortedFrameworkTargets] = new HashSet <int>();
                }
                frameworkTargetTypes.Add(databaseAddResult.TypeNameToTypeIndexMap[type]);
            }

            foreach (string sortedFrameworkTargets in frameworkTargetsToIncludedTypes.Keys)
            {
                int frameworkTargetsId   = this.StringStore.FindOrAddString(sortedFrameworkTargets);
                int frameworkTargetIndex = this.DeclaredMembers.Add(packageMemberIndex, frameworkTargetsId);
                this.DeclaredMemberTypes.Add(SymbolType.FrameworkTarget);

                // Now we'll add all types associated with this framework target set
                // To do so, we grab a single example from the source that expresses
                // the fully-qualified name, walk its tree, and add it to the target
                frameworkTargetTypes = frameworkTargetsToIncludedTypes[sortedFrameworkTargets];

                Stack <int> nodes = new Stack <int>();
                foreach (int typeIndex in frameworkTargetTypes)
                {
                    int           sourceMemberIndex = typeIndex;
                    SymbolDetails details           = source.DeclaredMemberDetails[sourceMemberIndex];

                    while (details.Type == SymbolType.Namespace || details.Type.IsType())
                    {
                        nodes.Push(sourceMemberIndex);
                        sourceMemberIndex = source.DeclaredMembers.GetParent(sourceMemberIndex);
                        details           = source.DeclaredMemberDetails[sourceMemberIndex];
                    }

                    int targetMemberIndex = frameworkTargetIndex;
                    while (nodes.Count > 0)
                    {
                        sourceMemberIndex = nodes.Pop();
                        details           = source.DeclaredMemberDetails[sourceMemberIndex];
                        int memberName = source.DeclaredMembers.GetNameIdentifier(sourceMemberIndex);
                        memberName = this.StringStore.FindOrAddString(source.StringStore[memberName]);

                        int indexInTarget;
                        if (!this.DeclaredMembers.TryFindChildByName(targetMemberIndex, memberName, out indexInTarget))
                        {
                            targetMemberIndex = this.DeclaredMembers.Add(targetMemberIndex, memberName);
                            this.Index.AddItem(memberName, targetMemberIndex);
                            this.DeclaredMemberTypes.Add(details.Type);
                        }
                        else
                        {
                            targetMemberIndex = indexInTarget;
                        }
                    }
                }
            }
        }