예제 #1
0
        private NodeViewModel CreateNodeViewModel(FileSystemEntry entry, NodeViewModel parent)
        {
            Invariants.Assert(entry != null);
            Invariants.Assert(parent != null);

            var directoryEntry = entry as DirectoryEntry;
            var node           = directoryEntry != null
        ? (NodeViewModel) new DirectoryNodeViewModel()
        : (NodeViewModel) new FileNodeViewModel();

            node.Caption = entry.Name;
            node.Name    = entry.Name;
            if (PathHelpers.IsAbsolutePath(node.Name))
            {
                node.Template = _templateFactory.ProjectTemplate;
            }
            else if (directoryEntry != null)
            {
                node.Template = _templateFactory.DirectoryTemplate;
            }
            else
            {
                var extension = Path.GetExtension(entry.Name);
                Invariants.Assert(extension != null);
                node.Template = _templateFactory.GetFileTemplate(extension);
                if (node.Template.Icon == null)
                {
                    if (!_fileTemplatesToInitialize.ContainsKey(extension))
                    {
                        _fileTemplatesToInitialize.Add(extension, node.Template);
                    }
                }
            }
            return(node);
        }
예제 #2
0
        private IIncrementalHierarchyBuilder CreateIncrementalBuilder(FileSystemTree fileSystemTree)
        {
            var vsHierarchy = _hierarchy as VsHierarchy;

            if (vsHierarchy != null)
            {
                return(new IncrementalHierarchyBuilder(
                           _nodeTemplateFactory,
                           vsHierarchy,
                           fileSystemTree,
                           _imageSourceFactory));
            }

            var vsHierarchyAggregate = _hierarchy as VsHierarchyAggregate;

            if (vsHierarchyAggregate != null)
            {
                return(new IncrementalHierarchyBuilderAggregate(
                           _nodeTemplateFactory,
                           vsHierarchyAggregate,
                           fileSystemTree,
                           _imageSourceFactory));
            }

            Invariants.Assert(false);
            return(null);
        }
예제 #3
0
        private void LoadFileContents(FileSystemEntities entities, FileContentsLoadingContext loadingContext, CancellationToken cancellationToken)
        {
            using (new TimeElapsedLogger("Loading file contents from disk", cancellationToken)) {
                using (var progress = _progressTrackerFactory.CreateTracker(entities.Files.Count)) {
                    entities.Files.AsParallelWrapper().ForAll(fileEntry => {
                        Invariants.Assert(fileEntry.Value.Contents == null);

                        // ReSharper disable once AccessToDisposedClosure
                        if (progress.Step())
                        {
                            // ReSharper disable once AccessToDisposedClosure
                            progress.DisplayProgress((i, n) =>
                                                     string.Format("Reading file {0:n0} of {1:n0}: {2}", i, n, fileEntry.Value.FileName.FullPath));

                            // Check for cancellation
                            if (cancellationToken.IsCancellationRequested)
                            {
                                loadingContext.PartialProgressReporter.ReportProgressNow();
                                cancellationToken.ThrowIfCancellationRequested();
                            }
                        }

                        var contents = LoadSingleFileContents(entities, loadingContext, fileEntry.Value);
                        if (contents != null)
                        {
                            entities.Files[fileEntry.Key] = fileEntry.Value.WithContents(contents);
                        }
                    });
                }
            }
            Logger.LogInfo("Loaded {0:n0} text files from disk, skipped {1:n0} binary files.",
                           loadingContext.LoadedTextFileCount,
                           loadingContext.LoadedBinaryFileCount);
        }
예제 #4
0
        private bool IsFileContentsUpToDate(FileSystemEntities entities, FullPathChanges fullPathChanges, FileWithContents existingFileWithContents)
        {
            Invariants.Assert(existingFileWithContents.Contents != null);

            var fullPath = existingFileWithContents.FileName.FullPath;

            if (fullPathChanges != null)
            {
                // We don't get file change events for file in symlinks, so we can't
                // rely on fullPathChanges contents for our heuristic of avoiding file
                // system access.
                if (!FileDatabaseSnapshot.IsContainedInSymLinkHelper(entities.Directories, existingFileWithContents.FileName))
                {
                    return(fullPathChanges.ShouldSkipLoadFileContents(fullPath));
                }
            }

            // Do the "expensive" check by going to the file system.
            var fi = _fileSystem.GetFileInfoSnapshot(fullPath);

            return
                ((fi.Exists) &&
                 (fi.IsFile) &&
                 (fi.LastWriteTimeUtc == existingFileWithContents.Contents.UtcLastModified));
        }
예제 #5
0
        private void RunNextTaskIfAvailableAsync(TaskEntry task)
        {
            TaskEntryQueue.DequeueResult queueEntry;
            lock (_lock) {
                if (task == null)
                {
                    // If there is a running task, bail, because we will be called again when the running task
                    // finishes.
                    if (_runningTask != null)
                    {
                        return;
                    }
                }
                else
                {
                    Invariants.Assert(ReferenceEquals(_runningTask, task));
                }
                queueEntry   = _taskQueue.Dequeue(_dateTimeProvider.UtcNow);
                _runningTask = queueEntry.TaskEntry; // May be null if only pdelayed tasks
            }

            if (queueEntry.TaskEntry != null)
            {
                // If there is a task available, run it
                RunTaskAsync(queueEntry.TaskEntry);
            }
            else if (queueEntry.HasPending)
            {
                // Run this method in a little while if there are pending tasks
                _customThreadPool.RunAsync(() => RunNextTaskIfAvailableAsync(null), TimeSpan.FromMilliseconds(50));
            }
        }
예제 #6
0
        private void RunTaskAsync(TaskEntry task)
        {
            Invariants.Assert(ReferenceEquals(_runningTask, task));
            _customThreadPool.RunAsync(() => {
                Invariants.Assert(ReferenceEquals(_runningTask, task));
                try {
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.LogDebug("Queue \"{0}\": Executing task \"{1}\" after waiting for {2:n0} msec",
                                        _description,
                                        task.Id.Description,
                                        (_dateTimeProvider.UtcNow - task.EnqueuedDateTimeUtc).TotalMilliseconds);
                    }

                    task.StopWatch.Start();
                    task.Action(_taskCancellationTracker.NewToken());
                } finally {
                    Invariants.Assert(ReferenceEquals(_runningTask, task));
                    task.StopWatch.Stop();
                    if (Logger.IsDebugEnabled)
                    {
                        Logger.LogDebug("Queue \"{0}\": Executed task \"{1}\" in {2:n0} msec",
                                        _description,
                                        task.Id.Description,
                                        task.StopWatch.ElapsedMilliseconds);
                    }
                    RunNextTaskIfAvailableAsync(task);
                }
            });
        }
예제 #7
0
        public static ArrayDiffsResult <T> BuildArrayDiffs <T>(
            IList <T> leftList,
            IList <T> rightList,
            IEqualityComparer <T> comparer)
        {
            comparer = comparer ?? EqualityComparer <T> .Default;

            var result = ProcessSpecialCases(leftList, rightList, comparer);

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

            bool smallList = leftList.Count + rightList.Count <= SmallArrayThreshold;
            var  result2   = smallList
        ? BuildArrayDiffsForSmallArrays(leftList, rightList, comparer)
        : BuildArrayDiffsForLargeArrays(leftList, rightList, comparer);

            // Quick check assumption about identity is verified: both list should not
            // contain duplicate elements.
            Invariants.Assert(
                result2.LeftOnlyItems.Count +
                result2.RightOnlyItems.Count +
                result2.CommonItems.Count * 2 ==
                leftList.Count + rightList.Count);
            return(result2);
        }
예제 #8
0
        public IFileDatabaseSnapshot BuildWithChangedFiles(IFileDatabaseSnapshot previousFileDatabaseSnapshot,
                                                           FileSystemSnapshot fileSystemSnapshot, IEnumerable <ProjectFileName> changedFiles,
                                                           Action onLoading, Action onLoaded, Action <IFileDatabaseSnapshot> onIntermadiateResult,
                                                           CancellationToken cancellationToken)
        {
            using (new TimeElapsedLogger("Building file database from previous one and list of changed files", cancellationToken, InfoLogger.Instance)) {
                Invariants.Assert(previousFileDatabaseSnapshot is FileDatabaseSnapshot);
                var previousFileDatabase = (FileDatabaseSnapshot)previousFileDatabaseSnapshot;

                // Update file contents of file data entries of changed files.
                var filesToRead = changedFiles
                                  .Where(x => x.Project.IsFileSearchable(x.FileName) && previousFileDatabase.Files.ContainsKey(x.FileName))
                                  .ToList();

                if (filesToRead.Count == 0)
                {
                    Logger.LogInfo("None of the changed file is searchable, return previous database snapshot");
                    return(previousFileDatabaseSnapshot);
                }

                // Read file contents.
                onLoading();
                filesToRead.ForAll(x => {
                    var newContents = _fileContentsFactory.ReadFileContents(x.FileName.FullPath);
                    DangerousUpdateFileTableEntry(previousFileDatabase, x.FileName, newContents);
                });
                onLoaded();

                // Return new file database with updated file contents.
                return(new FileDatabaseSnapshot(
                           previousFileDatabase.ProjectHashes,
                           previousFileDatabase.Directories,
                           previousFileDatabase.Files));
            }
        }
예제 #9
0
        public BuildOutputSpan ParseFullPath(string text)
        {
            var match = _fullPathRegex.Value.Match(text);

            if (!match.Success)
            {
                return(null);
            }

            var filenameMatch = match.Groups["filename"];
            var filename      = filenameMatch.Value;

            Invariants.Assert(!string.IsNullOrEmpty(filename), "RegEx is malformed: it should not match an empty filename");

            int line;
            int column;

            ParseLineColumn(match, out line, out column);

            return(new BuildOutputSpan {
                Text = text,
                Index = filenameMatch.Index,
                Length = match.Length - filenameMatch.Index,
                FileName = filename,
                LineNumber = line,
                ColumnNumber = column
            });
        }
예제 #10
0
        private IHierarchyObject PreviousSibling(IHierarchyObject item)
        {
            if (item == null)
            {
                return(null);
            }
            var parent = item.GetParent();

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

            IHierarchyObject previous = null;

            foreach (var child in parent.GetAllChildren())
            {
                if (child.Equals(item))
                {
                    return(previous);
                }
                previous = child;
            }
            Invariants.Assert(false);
            return(null);
        }
예제 #11
0
        private FileContents ReadFileContentsWorker(IFileInfoSnapshot fileInfo)
        {
            const int trailingByteCount = 2;
            var       block             = _fileSystem.ReadFileNulTerminated(fileInfo.Path, fileInfo.Length, trailingByteCount);
            var       contentsByteCount = block.ByteLength - trailingByteCount; // Padding added by ReadFileNulTerminated
            var       kind = NativeMethods.Text_GetKind(block.Pointer, contentsByteCount);

            switch (kind)
            {
            case NativeMethods.TextKind.TextKind_Ascii:
            // Note: Since we don't support UTF16 regex, just load all utf8 files as ascii.
            case NativeMethods.TextKind.TextKind_Utf8:
                return(new AsciiFileContents(new FileContentsMemory(block, 0, contentsByteCount), fileInfo.LastWriteTimeUtc));

            case NativeMethods.TextKind.TextKind_AsciiWithUtf8Bom:
            // Note: Since we don't support UTF16 regex, just load all utf8 files as ascii.
            case NativeMethods.TextKind.TextKind_Utf8WithBom:
                const int utf8BomSize = 3;
                return(new AsciiFileContents(new FileContentsMemory(block, utf8BomSize, contentsByteCount - utf8BomSize), fileInfo.LastWriteTimeUtc));

#if false
            case NativeMethods.TextKind.TextKind_Utf8WithBom:
                var utf16Block = Conversion.UTF8ToUnicode(block);
                block.Dispose();
                return(new Utf16FileContents(new FileContentsMemory(utf16Block, 0, utf16Block.ByteLength), fileInfo.LastWriteTimeUtc));
#endif
            case NativeMethods.TextKind.TextKind_ProbablyBinary:
                block.Dispose();
                return(new BinaryFileContents(fileInfo.LastWriteTimeUtc, fileInfo.Length));

            default:
                Invariants.Assert(false);
                throw new InvalidOperationException();
            }
        }
예제 #12
0
        private bool IsFileContentsUpToDate(FileSystemEntities entities,
                                            FullPathChanges fullPathChanges,
                                            FileWithContents existingFileWithContents)
        {
            Invariants.Assert(existingFileWithContents.Contents != null);

            var fullPath = existingFileWithContents.FileName.FullPath;

            if (fullPathChanges != null)
            {
                // We don't get file change events for file in symlinks, so we can't
                // rely on fullPathChanges contents for our heuristic of avoiding file
                // system access.
                // Actually, since we cannot reliable detect changes in symlinks, we enable this
                // optimization anyways, as we rely on the user to manually refresh the index
                // (that results in a "null" value for fullPathChanges)
                //if (!FileDatabaseSnapshot.IsContainedInSymLinkHelper(entities.Directories, existingFileWithContents.FileName)) {
                return(fullPathChanges.ShouldSkipLoadFileContents(fullPath));
                //}
            }

            // Do the "expensive" check by going to the file system.
            var fi = _fileSystem.GetFileInfoSnapshot(fullPath);

            return
                ((fi.Exists) &&
                 (fi.IsFile) &&
                 (fi.LastWriteTimeUtc == existingFileWithContents.Contents.UtcLastModified));
        }
예제 #13
0
        public FileExtract FilePositionSpanToFileExtract(FilePositionSpan filePositionSpan, int maxTextExtent)
        {
            maxTextExtent = Math.Max(maxTextExtent, filePositionSpan.Length);

            var spanStart = filePositionSpan.Position;
            var spanEnd   = spanStart + filePositionSpan.Length;

            var lineStart = GetLineStart(spanStart, maxTextExtent);
            var lineEnd   = GetLineEnd(spanEnd, maxTextExtent);

            // prefix - span - suffix
            var extractLength = lineEnd - lineStart;
            var spanLength    = filePositionSpan.Length;

            Invariants.Assert(spanLength <= extractLength);
            var prefixLength = Math.Min(spanStart - lineStart, maxTextExtent - spanLength);

            Invariants.Assert(prefixLength >= 0);
            var suffixLength = Math.Min(lineEnd - spanEnd, maxTextExtent - spanLength - prefixLength);

            Invariants.Assert(suffixLength >= 0);

            lineStart = spanStart - prefixLength;
            lineEnd   = spanEnd + suffixLength;
            var text    = GetText(lineStart, lineEnd - lineStart);
            var lineCol = GetLineColumn(spanStart);

            return(new FileExtract {
                Text = text,
                Offset = lineStart,
                Length = lineEnd - lineStart,
                LineNumber = lineCol.Item1,
                ColumnNumber = lineCol.Item2
            });
        }
예제 #14
0
        private void Grow()
        {
            Invariants.Assert(_count == _entries.Length);
            Invariants.Assert(_count == _buckets.Length);
            Invariants.Assert(_freeListHead == -1);
            var oldEntries = _entries;
            var oldLength  = _entries.Length;

            var newLength  = HashCode.GetPrime(GrowSize(oldLength));
            var newBuckets = new int[newLength];
            var newEntries = new Entry[newLength];

            Array.Copy(_entries, newEntries, _entries.Length);

            for (var entryIndex = 0; entryIndex < oldEntries.Length; entryIndex++)
            {
                var oldEntry = oldEntries[entryIndex];
                if (oldEntry.IsValid)
                {
                    var newBucketIndex = GetBucketIndex(oldEntry.HashCode, newLength);
                    newEntries[entryIndex].SetNextIndex(AdjustBucketIndexRead(newBuckets[newBucketIndex]));
                    newBuckets[newBucketIndex] = AdjustBucketIndexWrite(entryIndex);
                }
            }

            _buckets = newBuckets;
            _entries = newEntries;
        }
예제 #15
0
        public static int WrapQueryStatus(
            IOleCommandTarget receiver,
            IOleCommandTarget implementer,
            ref System.Guid pguidCmdGroup,
            uint cCmds,
            OLECMD[] prgCmds,
            System.IntPtr pCmdText)
        {
            Invariants.Assert(receiver != null);

            var commandId = new CommandID(pguidCmdGroup, (int)prgCmds[0].cmdID);

            if (LogCommand(commandId))
            {
                Logger.LogInfo("WrapQueryStatus: => recv={0}, impl={1}, parent={2}",
                               receiver,
                               GetImplementerString(implementer),
                               GetParentTargetString(implementer));
            }

            var hr = (implementer == null)
        ? (int)Constants.OLECMDERR_E_NOTSUPPORTED
        : implementer.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);

            if (LogCommand(commandId))
            {
                Logger.LogInfo("WrapQueryStatus: <= recv={0}, impl={1}, parent={2}, hr={3}, cmdf={4}",
                               receiver,
                               GetImplementerString(implementer),
                               GetParentTargetString(implementer),
                               HrToString(hr),
                               CmdFlagsToString(prgCmds));
            }
            return(hr);
        }
예제 #16
0
        public static NodeViewModel CreateNodeViewModel(INodeTemplateFactory templateFactory, FileSystemEntry entry,
                                                        NodeViewModel parent)
        {
            Invariants.Assert(entry != null);
            Invariants.Assert(parent != null);

            var directoryEntry = entry as DirectoryEntry;
            var node           = directoryEntry != null
        ? (NodeViewModel) new DirectoryNodeViewModel(parent)
        : (NodeViewModel) new FileNodeViewModel(parent);

            node.Caption = entry.Name;
            node.Name    = entry.Name;
            if (PathHelpers.IsAbsolutePath(node.Name))
            {
                node.Template = templateFactory.ProjectTemplate;
            }
            else if (directoryEntry != null)
            {
                node.Template = templateFactory.DirectoryTemplate;
            }
            else
            {
                var extension = Path.GetExtension(entry.Name);
                Invariants.Assert(extension != null);
                node.Template = templateFactory.GetFileTemplate(extension);
            }

            return(node);
        }
예제 #17
0
        private void ComputeNewStateLongTask(FileSystemSnapshot previousSnapshot, FileSystemSnapshot newSnapshot,
                                             FullPathChanges fullPathChanges,
                                             CancellationToken cancellationToken)
        {
            Invariants.Assert(_inTaskQueueTask);

            UpdateFileDatabase(newSnapshot, options => {
                // We only allow incremental updates if the last update was successfully completed
                // and if the file system snapshot version we are based on is the same as the
                // new file system snapshot we are processing
                if (previousSnapshot.Version == _currentFileSystemSnapshotVersion &&
                    options.PreviousUpdateCompleted &&
                    fullPathChanges != null)
                {
                    return(CreateWithFileSystemChanges(newSnapshot, fullPathChanges, options, cancellationToken));
                }
                else
                {
                    Logger.LogInfo($"Starting a full database update: " +
                                   $"CurrentSnapshotVersion={_currentFileSystemSnapshotVersion}, " +
                                   $"PreviousUpdateCompleted={options.PreviousUpdateCompleted}, " +
                                   $"PreviousSnapshotVersion={previousSnapshot.Version}, " +
                                   $"FullPathChanges={fullPathChanges?.Entries.Count ?? -1}.");
                    return(CreateFullScan(newSnapshot, options, cancellationToken));
                }
            });
        }
예제 #18
0
        private IHierarchyObject NextSibling(IHierarchyObject item)
        {
            if (item == null)
            {
                return(null);
            }
            var parent = item.GetParent();

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

            bool found = false;

            foreach (var child in parent.GetAllChildren())
            {
                if (found)
                {
                    return(child);
                }
                if (child.Equals(item))
                {
                    found = true;
                }
            }
            Invariants.Assert(found);
            return(null);
        }
예제 #19
0
        private void ActivateCurrentDatabase(FileSystemSnapshot fileSystemSnapshot, IFileDatabaseSnapshot databaseSnapshot, bool complete)
        {
            Invariants.Assert(_inTaskQueueTask);

            _currentFileDatabase = databaseSnapshot;
            _currentFileSystemSnapshotVersion = fileSystemSnapshot.Version;
            _previousUpdateCompleted          = complete; // Success => we allow incremtal updates next time
        }
        public Func <int, ApplyChangesResult> ComputeChangeApplier()
        {
            // Capture hierarchy version # for checking later that another
            // thread did not beat us.
            int hierarchyVersion = _hierarchy.Version;
            var oldHierarchies   = _hierarchy.CloneHierarchyList();

            // For new hierarchies: create tree and compute nodes
            // For comon existing hierarchies: create tree and compute nodes
            // For removed hierarchies: create (empty) tree and compute nodes
            List <RootEntry> rootEntries = CreateRootEntries(oldHierarchies).ToList();

            rootEntries.ForAll(entry => {
                entry.ChangeApplier = entry.Builder.ComputeChangeApplier();
            });

            return(latestFileSystemTreeVersion => {
                // Apply if nobody beat us to is.
                if (_hierarchy.Version == hierarchyVersion)
                {
                    Logger.LogInfo(
                        "Updating VsHierarchyAggregate nodes for version {0} and file system tree version {1}",
                        hierarchyVersion,
                        _fileSystemTree.Version);
                    rootEntries.ForAll(entry => {
                        var result = entry.ChangeApplier(latestFileSystemTreeVersion);
                        Invariants.Assert(result == ApplyChangesResult.Done);
                    });
                    var newHierarchies = rootEntries
                                         .Where(x => !x.Hierarchy.IsEmpty)
                                         .Select(x => x.Hierarchy)
                                         .ToList();
                    _hierarchy.SetNewHierarchies(newHierarchies);
                    return ApplyChangesResult.Done;
                }

                Logger.LogInfo(
                    "VsHierarchyAggregate nodes have been updated concurrently, re-run or skip operation." +
                    " Node verions={0}-{1}, Tree versions:{2}-{3}.",
                    hierarchyVersion, _hierarchy.Version,
                    _fileSystemTree.Version, latestFileSystemTreeVersion);

                // If the version of the hieararchy has changed since when we started,
                // another thread has passed us.  This means the decisions we made
                // about the changes to apply are incorrect at this point. So, we run
                // again if we are processing the latest known version of the file
                // system tree, as we should be the winner (eventually)
                if (_fileSystemTree.Version == latestFileSystemTreeVersion)
                {
                    // Termination notes: We make this call only when the VsHierarchy
                    // version changes between the time we capture it and this point.
                    return ApplyChangesResult.Retry;
                }

                return ApplyChangesResult.Bail;
            });
        }
예제 #21
0
 public void AddNode(NodeViewModel node)
 {
     Invariants.Assert(node.ItemId != VSConstants.VSITEMID_NIL);
     _itemIdMap.Add(node.ItemId, node);
     if (node.ItemId != RootNodeItemId)
     {
         _maxItemId = Math.Max(_maxItemId, node.ItemId);
     }
 }
예제 #22
0
        private void TreeViewScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            Invariants.Assert(_treeViewScrollViewer != null);

            if (_treeViewResetHorizScroll)
            {
                _treeViewScrollViewer.ScrollToHorizontalOffset(_treeViewHorizScrollPos);
                _treeViewResetHorizScroll = false;
            }
        }
예제 #23
0
 private DirectoryName GetAncestor(DirectoryName x, int count)
 {
     Invariants.Assert(x != null);
     for (var i = 0; i < count; i++)
     {
         x = x.Parent;
     }
     Invariants.Assert(x != null);
     return(x);
 }
예제 #24
0
        private static int MapIndexOf <T>(IDictionary <T, int> items, T item)
        {
            int result;

            if (!items.TryGetValue(item, out result))
            {
                return(-1);
            }
            Invariants.Assert(result >= 0);
            return(result);
        }
예제 #25
0
        private Tuple <int, int> GetLineColumn(int offset)
        {
            var lineNumber = GetLineStartIndex(offset);

            Invariants.Assert(lineNumber >= 0);
            Invariants.Assert(lineNumber < _listStartOffsets.Count);

            var columnNumber = offset - _listStartOffsets[lineNumber];

            return(Tuple.Create(lineNumber, columnNumber));
        }
예제 #26
0
        public static int WrapExec(
            IOleCommandTarget receiver,
            IOleCommandTarget implementer,
            ref System.Guid pguidCmdGroup,
            uint nCmdID,
            uint nCmdexecopt,
            System.IntPtr pvaIn,
            System.IntPtr pvaOut)
        {
            Invariants.Assert(receiver != null);

            var commandId = new CommandID(pguidCmdGroup, (int)nCmdID);

            if (LogCommand(commandId))
            {
                Logger.LogInfo("WrapExec: => recv={0}, impl={1}, parent={2}",
                               receiver,
                               GetImplementerString(implementer),
                               GetParentTargetString(implementer));
            }

            var hr = (implementer == null)
        ? (int)Constants.OLECMDERR_E_NOTSUPPORTED
        : implementer.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);

            // Ensures OleMenuCommandService returns OLECMDERR_E_NOTSUPPORTED.
            if (hr == VSConstants.S_OK && implementer is OleMenuCommandService)
            {
                // Ensure we return OLECMDERR_E_NOTSUPPORTED instead of S_OK if our
                // command does not support the command id. This is necessary so that
                // the VS Shell chains the Exec call to other IOleCommandTarget
                // implementations.
                var service = (OleMenuCommandService)implementer;
                var command = service.FindCommand(commandId);
                if (command != null)
                {
                    if (!command.Supported)
                    {
                        hr = (int)Constants.OLECMDERR_E_NOTSUPPORTED;
                    }
                }
            }

            if (LogCommand(commandId))
            {
                Logger.LogInfo("WrapExec: <= recv={0}, impl={1}, parent={2}, hr={3}",
                               receiver,
                               GetImplementerString(implementer),
                               GetParentTargetString(implementer),
                               HrToString(hr));
            }
            return(hr);
        }
예제 #27
0
 private int GetDistanceToAbsolutePath(DirectoryName x)
 {
     Invariants.Assert(x != null);
     for (int result = 0;; result++)
     {
         if (x is AbsoluteDirectoryName)
         {
             return(result);
         }
         x = x.Parent;
         Invariants.Assert(x != null);
     }
 }
예제 #28
0
        public static T ExecuteAndWait <T>(this ITaskQueue queue, Func <CancellationToken, T> task)
        {
            var result = default(T);
            var e      = new ManualResetEvent(false);

            queue.ExecuteAsync(token => {
                result = task(token);
                e.Set();
            });
            e.WaitOne();
            Invariants.Assert(result != null);
            return(result);
        }
예제 #29
0
        /// <summary>
        /// Returns the item (or null) directly following <paramref name="item"/> in
        /// "previous sibling, parent" order.
        /// </summary>
        public IHierarchyObject GetPreviousItem(IHierarchyObject item)
        {
            if (item == null)
            {
                return(null);
            }

            // a
            //   b
            //     c
            //     d
            // e
            //
            // Return "b" is we are on "c"
            // Return "d" if we are on "e"
            // Return "e" if we are on "a"
            // Return "a" if we are on "b"
            //
            var result = PreviousSibling(item);

            if (result == null)
            {
                var parent = item.GetParent();
                if (parent != null)
                {
                    return(parent);
                }
                // "a" case: get the very last child at the bottom of the tree
                while (true)
                {
                    Invariants.Assert(item != null);
                    var last = LastChild(item);
                    if (last == null)
                    {
                        return(item);
                    }
                    item = last;
                }
            }

            while (true)
            {
                Invariants.Assert(result != null);
                var last = LastChild(result);
                if (last == null)
                {
                    return(result);
                }
                result = last;
            }
        }
예제 #30
0
        private int GetLineStartIndex(int offset)
        {
            Invariants.Assert(offset >= 0);
            Invariants.Assert(_listStartOffsets[0] == 0);

            var result = _listStartOffsets.BinarySearch(offset);

            if (result < 0)
            {
                var insertionIndex = ~result;
                return(insertionIndex - 1);
            }
            return(result);
        }