提交 8813f49a 编写于 作者: H Heejae Chang

Merge pull request #4341 from heejaechang/projectkmerged

remove error list dead code
......@@ -49,6 +49,11 @@ internal class VisualStudioDiagnosticListTable : VisualStudioBaseDiagnosticListT
private ITableDataSource GetCurrentDataSource()
{
if (_errorList == null)
{
return _liveTableSource;
}
return _errorList.AreOtherErrorSourceEntriesShown ? (ITableDataSource)_liveTableSource : _buildTableSource;
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
internal abstract partial class AbstractVisualStudioErrorTaskList
{
private class VisualStudioTaskItem : VisualStudioTaskItemBase<IErrorTaskItem>, IComparable<VisualStudioTaskItem>
{
public VisualStudioTaskItem(IErrorTaskItem item) :
base(VSTASKCATEGORY.CAT_BUILDCOMPILE, item)
{
}
public int CompareTo(VisualStudioTaskItem other)
{
Contract.Requires(this.ItemCategory == other.ItemCategory);
Contract.Requires(this.Info.Workspace == other.Info.Workspace);
Contract.Requires(this.Info.Workspace is VisualStudioWorkspace);
return ProjectCompareTo(this.Info.Workspace.CurrentSolution, this.Info, other.Info);
}
private int ProjectCompareTo(Solution solution, IErrorTaskItem left, IErrorTaskItem right)
{
var project1 = solution.GetProject(left.ProjectId);
var project2 = solution.GetProject(right.ProjectId);
// existing project goes first
var result = NullCompareTo(project1, project2);
if (result != 0)
{
return result;
}
// project doesn't exist, document won't exist as well.
if (project1 == null && project2 == null)
{
// compare just information it has
return InfoCompareTo(left, right);
}
// project name
var name = string.Compare(project1.Name, project2.Name, StringComparison.OrdinalIgnoreCase);
if (name != 0)
{
return name;
}
// document
return DocumentCompareTo(solution, left, right);
}
private int DocumentCompareTo(Solution solution, IErrorTaskItem left, IErrorTaskItem right)
{
var document1 = solution.GetDocument(left.DocumentId);
var document2 = solution.GetDocument(right.DocumentId);
// existing document goes first
var result = NullCompareTo(document1, document2);
if (result != 0)
{
return result;
}
// document doesn't exist
if (document1 == null && document2 == null)
{
return InfoCompareTo(left, right);
}
// document filepath or name
int nameResult = 0;
if (document1.FilePath != null && document1.FilePath != null)
{
nameResult = string.Compare(document1.FilePath, document2.FilePath, StringComparison.OrdinalIgnoreCase);
}
else
{
nameResult = string.Compare(document1.Name, document2.Name, StringComparison.OrdinalIgnoreCase);
}
if (nameResult != 0)
{
return nameResult;
}
return InfoCompareTo(left, right);
}
private int InfoCompareTo(IErrorTaskItem left, IErrorTaskItem right)
{
if (left.DocumentId == null && right.DocumentId == null)
{
return string.Compare(left.Message, right.Message);
}
Contract.Requires(left.DocumentId != null && right.DocumentId != null);
var line = left.OriginalLine - right.OriginalLine;
if (line != 0)
{
return line;
}
var column = left.OriginalColumn - right.OriginalColumn;
if (column != 0)
{
return column;
}
return string.Compare(left.Message, right.Message);
}
private int NullCompareTo(object left, object right)
{
if (left != null && right == null)
{
return -1;
}
else if (left == null && right != null)
{
return 1;
}
return 0;
}
public override bool Equals(object obj)
{
return Equals(obj as VisualStudioTaskItem);
}
public bool Equals(VisualStudioTaskItem other)
{
if (this == other)
{
return true;
}
return base.Equals(other) &&
this.Info.ProjectId == other.Info.ProjectId &&
this.Info.Severity == other.Info.Severity &&
this.Info.Id == other.Info.Id;
}
public override int GetHashCode()
{
return
Hash.Combine(base.GetHashCode(),
Hash.Combine(this.Info.ProjectId,
Hash.Combine((int)this.Info.Severity,
Hash.Combine(this.Info.Id, 0))));
}
public override int GetCategory(out uint pCategory)
{
pCategory = (uint)GetErrorCategory(this.Info.Severity);
return VSConstants.S_OK;
}
public override int GetHierarchy(out IVsHierarchy hierarchy)
{
var workspace = this.Info.Workspace as VisualStudioWorkspace;
if (workspace == null)
{
hierarchy = null;
return VSConstants.E_NOTIMPL;
}
hierarchy = workspace.GetHierarchy(this.Info.ProjectId);
return VSConstants.S_OK;
}
protected override int GetPriority(VSTASKPRIORITY[] ptpPriority)
{
if (ptpPriority != null)
{
switch (GetErrorCategory(this.Info.Severity))
{
case TaskErrorCategory.Error:
ptpPriority[0] = VSTASKPRIORITY.TP_HIGH;
break;
case TaskErrorCategory.Warning:
ptpPriority[0] = VSTASKPRIORITY.TP_NORMAL;
break;
case TaskErrorCategory.Message:
ptpPriority[0] = VSTASKPRIORITY.TP_LOW;
break;
default:
return VSConstants.E_FAIL;
}
return VSConstants.S_OK;
}
return VSConstants.E_FAIL;
}
private TaskErrorCategory GetErrorCategory(DiagnosticSeverity severity)
{
switch (severity)
{
default:
case DiagnosticSeverity.Error:
return TaskErrorCategory.Error;
case DiagnosticSeverity.Warning:
return TaskErrorCategory.Warning;
case DiagnosticSeverity.Info:
return TaskErrorCategory.Message;
}
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
/// <summary>
/// Since we're using the latest IVsTaskList3 RefreshOrAddTasksAsync and RemoveTasksAsync
/// APIs, we won't normally need to enumerate over each task list item.
///
/// The only exception to this is if someone were to call RefreshAllProviders. If we
/// want to handle that case, we should simply raise an event here that causes RoslynVSTaskList
/// to re-add all of our items. This is a terrible waste though and should never happen to us.
/// </summary>
internal abstract partial class AbstractVisualStudioTaskList : IVsTaskProvider
{
// This gets called once when we register, but shouldn't get called again
// except build case. in build case, VS will refresh all errors at the end of build
public virtual int EnumTaskItems(out IVsEnumTaskItems ppenum)
{
ppenum = new EmptyVsEnumTaskItems();
return VSConstants.S_OK;
}
public int ImageList(out IntPtr imageList)
{
imageList = default(IntPtr);
return VSConstants.E_NOTIMPL;
}
public int OnTaskListFinalRelease(IVsTaskList taskList)
{
return VSConstants.E_NOTIMPL;
}
public int ReRegistrationKey(out string key)
{
key = null;
return VSConstants.E_NOTIMPL;
}
public int SubcategoryList(uint cbstr, string[] str, out uint actual)
{
actual = default(uint);
return VSConstants.E_NOTIMPL;
}
private class EmptyVsEnumTaskItems : IVsEnumTaskItems
{
public int Clone(out IVsEnumTaskItems ppenum)
{
ppenum = null;
return VSConstants.E_NOTIMPL;
}
public int Next(uint celt, IVsTaskItem[] rgelt, uint[] pceltFetched)
{
return VSConstants.E_NOTIMPL;
}
public int Reset()
{
return VSConstants.E_NOTIMPL;
}
public int Skip(uint celt)
{
return VSConstants.E_NOTIMPL;
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
internal abstract partial class AbstractVisualStudioTaskList : IVsTaskProvider
{
protected readonly bool ErrorListInstalled;
protected readonly IServiceProvider ServiceProvider;
protected readonly IAsynchronousOperationListener Listener;
protected readonly IForegroundNotificationService NotificationService;
private uint _providerCookie;
private IVsTaskList3 _tasklist;
protected AbstractVisualStudioTaskList(
IServiceProvider serviceProvider,
IForegroundNotificationService notificationService,
string featureName,
IEnumerable<Lazy<IAsynchronousOperationListener, FeatureMetadata>> asyncListeners)
{
Contract.ThrowIfNull(serviceProvider);
this.ServiceProvider = serviceProvider;
this.NotificationService = notificationService;
this.Listener = new AggregateAsynchronousOperationListener(asyncListeners, featureName);
// TODO: remove this type and its derived types.
// now, new error list is installed by default, and no way to take it out.
// set ErrorListInstalled to true
this.ErrorListInstalled = true;
}
/// <summary>
/// should be called from derived class since registering task list will call us back to enumerate existing task items.
/// </summary>
protected void InitializeTaskList()
{
_tasklist = ServiceProvider.GetService(typeof(SVsTaskList)) as IVsTaskList3;
Contract.ThrowIfNull(_tasklist);
Contract.ThrowIfNull(_tasklist as IVsTaskList); // IVsTaskList3 doesn't implement IVsTaskList.
Contract.ThrowIfFalse(((IVsTaskList)_tasklist).RegisterTaskProvider(this, out _providerCookie) == VSConstants.S_OK);
}
protected IVsTask RemoveTasks(IVsTaskItem[] oldTasks)
{
return _tasklist.RemoveTasksAsync(_providerCookie, oldTasks.Length, oldTasks);
}
protected IVsTask RefreshOrAddTasks(IVsTaskItem[] newTasks)
{
if (newTasks.Length <= 0)
{
return null;
}
// Don't update more than this many items at a time to avoid perf problems
const int MaxTasksToAddInOneCall = 50;
if (newTasks.Length <= MaxTasksToAddInOneCall)
{
return _tasklist.RefreshOrAddTasksAsync(_providerCookie, newTasks.Length, newTasks);
}
else
{
var arraySubset = new IVsTaskItem[MaxTasksToAddInOneCall];
IVsTask lastTask = null;
for (int i = 0; i < newTasks.Length; i += MaxTasksToAddInOneCall)
{
var subsetSize = Math.Min(MaxTasksToAddInOneCall, newTasks.Length - i);
if (subsetSize > 0)
{
Array.Copy(newTasks, i, arraySubset, 0, subsetSize);
lastTask = _tasklist.RefreshOrAddTasksAsync(_providerCookie, subsetSize, arraySubset);
}
}
// we only need last task. VS already serialize request internally
return lastTask;
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.ComponentModel;
using System.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Implementation.TodoComments;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
using Microsoft.VisualStudio.LanguageServices.Implementation.Options;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
[ExportOptionSerializer(TodoCommentOptions.OptionName), Shared]
internal class CommentTaskTokenSerializer : IOptionSerializer
{
// it seems VS doesn't give a way to get notified if this setting gets changed.
// so we will only read it once and keep using it until next vs run
private readonly string _taskTokenList;
private readonly ITaskList _taskList;
private readonly IOptionService _optionService;
private string _lastCommentTokenCache = null;
[ImportingConstructor]
public CommentTaskTokenSerializer(SVsServiceProvider serviceProvider)
public CommentTaskTokenSerializer(
SVsServiceProvider serviceProvider, IOptionService optionService)
{
var tokenInfo = serviceProvider.GetService(typeof(SVsTaskList)) as IVsCommentTaskInfo;
_optionService = optionService;
_taskList = serviceProvider.GetService(typeof(SVsTaskList)) as ITaskList;
_lastCommentTokenCache = GetTaskTokenList(_taskList);
// The SVsTaskList may not be available (e.g. during "devenv /build")
_taskTokenList = tokenInfo != null ? GetTaskTokenList(tokenInfo) : string.Empty;
if (_taskList != null)
{
_taskList.PropertyChanged += OnPropertyChanged;
}
}
public bool TryFetch(OptionKey optionKey, out object value)
......@@ -37,7 +44,7 @@ public bool TryFetch(OptionKey optionKey, out object value)
return false;
}
value = _taskTokenList;
value = _lastCommentTokenCache;
return true;
}
......@@ -47,44 +54,49 @@ public bool TryPersist(OptionKey optionKey, object value)
return false;
}
public static string GetTaskTokenList(IVsCommentTaskInfo tokenInfo)
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
int tokenCount;
if (Succeeded(tokenInfo.TokenCount(out tokenCount)) && tokenCount > 0)
if (e.PropertyName != nameof(ITaskList.CommentTokens))
{
var tokens = new IVsCommentTaskToken[tokenCount];
var tokensEnum = default(IVsEnumCommentTaskTokens);
if (Succeeded(tokenInfo.EnumTokens(out tokensEnum)))
{
uint count;
if (Succeeded(tokensEnum.Next((uint)tokenCount, tokens, out count)))
{
Contract.Requires(tokenCount == count);
string text;
var priority = new VSTASKPRIORITY[1];
var result = new List<string>();
foreach (var token in tokens)
{
if (Succeeded(token.Text(out text)) &&
Succeeded(token.Priority(priority)) &&
!string.IsNullOrWhiteSpace(text))
{
result.Add(string.Format("{0}:{1}", text, (int)priority[0]));
}
}
return string.Join("|", result);
}
}
return;
}
var commentString = GetTaskTokenList(_taskList);
var optionSet = _optionService.GetOptions();
var optionValue = optionSet.GetOption(TodoCommentOptions.TokenList);
if (optionValue == commentString)
{
return;
}
return string.Empty;
// cache last result
_lastCommentTokenCache = commentString;
// let people to know that comment string has changed
_optionService.SetOptions(optionSet.WithChangedOption(TodoCommentOptions.TokenList, _lastCommentTokenCache));
}
private static bool Succeeded(int hr)
private static string GetTaskTokenList(ITaskList taskList)
{
return hr == VSConstants.S_OK;
var commentTokens = taskList?.CommentTokens;
if (commentTokens == null || commentTokens.Count == 0)
{
return string.Empty;
}
var result = new List<string>();
foreach (var commentToken in commentTokens)
{
if (string.IsNullOrWhiteSpace(commentToken.Text))
{
continue;
}
result.Add($"{commentToken.Text}:{((int)commentToken.Priority).ToString()}");
}
return string.Join("|", result);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.Shell;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
[Export(typeof(VisualStudioErrorTaskList))]
internal partial class VisualStudioErrorTaskList : AbstractVisualStudioErrorTaskList
{
[ImportingConstructor]
public VisualStudioErrorTaskList(
SVsServiceProvider serviceProvider,
VisualStudioWorkspace workspace,
IForegroundNotificationService notificationService,
IDiagnosticService diagnosticService,
[ImportMany] IEnumerable<Lazy<IAsynchronousOperationListener, FeatureMetadata>> asyncListeners) :
base(serviceProvider, workspace, notificationService, diagnosticService, asyncListeners)
{
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Navigation;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.Implementation.Venus;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
using VsTextSpan = Microsoft.VisualStudio.TextManager.Interop.TextSpan;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
internal class VisualStudioTaskItemBase<T> : IVsErrorItem, IVsTaskItem where T : class, ITaskItem
{
protected readonly VSTASKCATEGORY ItemCategory;
internal readonly T Info;
protected VisualStudioTaskItemBase(VSTASKCATEGORY category, T taskItem)
{
this.ItemCategory = category;
this.Info = taskItem;
}
protected ContainedDocument GetContainedDocumentFromWorkspace()
{
var visualStudioWorkspace = this.Info.Workspace as VisualStudioWorkspaceImpl;
if (visualStudioWorkspace == null)
{
return null;
}
return visualStudioWorkspace.GetHostDocument(this.Info.DocumentId) as ContainedDocument;
}
/// <summary>
/// Gets the display location of the tasklist item. This is the same as the navigation
/// location except for Venus which must have their original
/// unmapped line numbers mapped through its buffer coordinator.
/// </summary>
protected VsTextSpan GetDisplayLocation()
{
var containedDocument = GetContainedDocumentFromWorkspace();
if (containedDocument != null)
{
var displayLocation = new VsTextSpan()
{
iStartLine = this.Info.OriginalLine,
iStartIndex = this.Info.OriginalColumn,
iEndLine = this.Info.OriginalLine,
iEndIndex = this.Info.OriginalColumn
};
var containedLanguage = containedDocument.ContainedLanguage;
var bufferCoordinator = containedLanguage.BufferCoordinator;
var containedLanguageHost = containedLanguage.ContainedLanguageHost;
var mappedLocation = new VsTextSpan[1];
if (VSConstants.S_OK == bufferCoordinator.MapSecondaryToPrimarySpan(displayLocation, mappedLocation))
{
return mappedLocation[0];
}
else if (containedLanguageHost != null && VSConstants.S_OK == containedLanguageHost.GetNearestVisibleToken(displayLocation, mappedLocation))
{
return mappedLocation[0];
}
}
return GetMappedLocation();
}
/// <summary>
/// Gets the location to be used when navigating to the item. This is the same
/// as the display location except for Venus which must use their
/// original unmapped location as the navigation location so that it can be
/// translated correctly during navigation.
/// </summary>
protected VsTextSpan GetNavigationLocation()
{
var containedDocument = GetContainedDocumentFromWorkspace();
if (containedDocument != null)
{
return new VsTextSpan()
{
iStartLine = this.Info.OriginalLine,
iStartIndex = this.Info.OriginalColumn,
iEndLine = this.Info.OriginalLine,
iEndIndex = this.Info.OriginalColumn
};
}
return GetMappedLocation();
}
private VsTextSpan GetMappedLocation()
{
if (this.Info.DocumentId != null)
{
return new VsTextSpan
{
iStartLine = this.Info.MappedLine,
iStartIndex = this.Info.MappedColumn,
iEndLine = this.Info.MappedLine,
iEndIndex = this.Info.MappedColumn
};
}
return new VsTextSpan();
}
public override bool Equals(object obj)
{
return Equals(obj as VisualStudioTaskItemBase<T>);
}
protected bool Equals(VisualStudioTaskItemBase<T> other)
{
if (this == other)
{
return true;
}
if (this.Info == other.Info)
{
return true;
}
if (this.Info.DocumentId != null && other.Info.DocumentId != null)
{
return
this.ItemCategory == other.ItemCategory &&
this.Info.DocumentId == other.Info.DocumentId &&
this.Info.Message == other.Info.Message &&
this.Info.OriginalColumn == other.Info.OriginalColumn &&
this.Info.OriginalLine == other.Info.OriginalLine &&
this.Info.MappedColumn == other.Info.MappedColumn &&
this.Info.MappedLine == other.Info.MappedLine &&
this.Info.MappedFilePath == other.Info.MappedFilePath;
}
return
this.ItemCategory == other.ItemCategory &&
this.Info.DocumentId == other.Info.DocumentId &&
this.Info.Message == other.Info.Message &&
this.Info.MappedFilePath == other.Info.MappedFilePath;
}
public override int GetHashCode()
{
if (this.Info.DocumentId != null)
{
return
Hash.Combine((int)this.ItemCategory,
Hash.Combine(this.Info.DocumentId,
Hash.Combine(this.Info.Message,
Hash.Combine(this.Info.MappedFilePath,
Hash.Combine(this.Info.OriginalColumn,
Hash.Combine(this.Info.OriginalLine,
Hash.Combine(this.Info.MappedColumn,
Hash.Combine(this.Info.MappedLine, 0))))))));
}
return
Hash.Combine((int)this.ItemCategory,
Hash.Combine(this.Info.DocumentId,
Hash.Combine(this.Info.Message,
Hash.Combine(this.Info.MappedFilePath, 0))));
}
public virtual int CanDelete(out int pfCanDelete)
{
pfCanDelete = 0;
return VSConstants.S_OK;
}
public virtual int GetCategory(out uint pCategory)
{
pCategory = (uint)TaskErrorCategory.Error;
return VSConstants.S_OK;
}
public virtual int ImageListIndex(out int pIndex)
{
pIndex = (int)_vstaskbitmap.BMP_COMPILE;
return VSConstants.E_NOTIMPL;
}
public virtual int IsReadOnly(VSTASKFIELD field, out int pfReadOnly)
{
pfReadOnly = 1;
return VSConstants.S_OK;
}
public virtual int HasHelp(out int pfHasHelp)
{
pfHasHelp = 0;
return VSConstants.S_OK;
}
public virtual int GetHierarchy(out IVsHierarchy ppProject)
{
ppProject = null;
return VSConstants.S_OK;
}
public virtual int NavigateToHelp()
{
return VSConstants.E_NOTIMPL;
}
public virtual int OnDeleteTask()
{
return VSConstants.E_NOTIMPL;
}
public virtual int OnFilterTask(int fVisible)
{
return VSConstants.E_NOTIMPL;
}
protected virtual int GetChecked(out int pfChecked)
{
pfChecked = 0;
return VSConstants.S_OK;
}
protected virtual int GetPriority(VSTASKPRIORITY[] ptpPriority)
{
if (ptpPriority != null)
{
ptpPriority[0] = VSTASKPRIORITY.TP_NORMAL;
}
return VSConstants.S_OK;
}
protected virtual int PutChecked(int fChecked)
{
return VSConstants.E_NOTIMPL;
}
protected virtual int PutPriority(VSTASKPRIORITY tpPriority)
{
return VSConstants.E_NOTIMPL;
}
protected virtual int PutText(string bstrName)
{
return VSConstants.E_NOTIMPL;
}
public virtual int SubcategoryIndex(out int pIndex)
{
pIndex = 0;
return VSConstants.E_NOTIMPL;
}
public int Category(VSTASKCATEGORY[] pCat)
{
if (pCat != null)
{
pCat[0] = ItemCategory;
}
return VSConstants.S_OK;
}
public int Line(out int line)
{
if (this.Info.DocumentId == null)
{
line = 0;
return VSConstants.E_NOTIMPL;
}
var displayLocation = this.GetDisplayLocation();
line = displayLocation.iStartLine;
return VSConstants.S_OK;
}
public int Column(out int column)
{
if (this.Info.DocumentId == null)
{
column = 0;
return VSConstants.E_NOTIMPL;
}
var displayLocation = this.GetDisplayLocation();
column = displayLocation.iStartIndex;
return VSConstants.S_OK;
}
public int Document(out string documentPath)
{
if (this.Info.DocumentId == null)
{
documentPath = null;
return VSConstants.E_NOTIMPL;
}
// // TODO (bug 904049): the path may be relative and should to be resolved with OriginalFilePath as its base
documentPath = this.Info.MappedFilePath;
return VSConstants.S_OK;
}
public int NavigateTo()
{
using (Logger.LogBlock(FunctionId.TaskList_NavigateTo, CancellationToken.None))
{
if (this.Info.DocumentId == null)
{
// Some items do not have a location in a document
return VSConstants.E_NOTIMPL;
}
// TODO (bug 904049): We should not navigate to the documentId if diagnosticItem.MappedFilePath is available.
// We should find the corresponding document if it exists.
var workspace = this.Info.Workspace;
var documentId = this.Info.DocumentId;
var document = workspace.CurrentSolution.GetDocument(documentId);
if (document == null)
{
// document could be already removed from the solution
return VSConstants.E_NOTIMPL;
}
var navigationService = workspace.Services.GetService<IDocumentNavigationService>();
var navigationLocation = this.GetNavigationLocation();
navigationService.TryNavigateToLineAndOffset(
workspace, documentId, navigationLocation.iStartLine, navigationLocation.iStartIndex);
return VSConstants.S_OK;
}
}
// use explicit interface to workaround style cop complaints
int IVsTaskItem.get_Text(out string text)
{
text = this.Info.Message;
return VSConstants.S_OK;
}
int IVsTaskItem.get_Checked(out int pfChecked)
{
return GetChecked(out pfChecked);
}
int IVsTaskItem.get_Priority(VSTASKPRIORITY[] ptpPriority)
{
return GetPriority(ptpPriority);
}
int IVsTaskItem.put_Checked(int fChecked)
{
return PutChecked(fChecked);
}
int IVsTaskItem.put_Priority(VSTASKPRIORITY tpPriority)
{
return PutPriority(tpPriority);
}
int IVsTaskItem.put_Text(string bstrName)
{
return PutText(bstrName);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.Editor.Implementation.TodoComments;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
internal partial class VisualStudioTodoTaskList
{
private class VisualStudioTaskItem : VisualStudioTaskItemBase<TodoTaskItem>
{
private bool _checked;
public VisualStudioTaskItem(TodoTaskItem item)
: base(VSTASKCATEGORY.CAT_COMMENTS, item)
{
_checked = false;
}
public override bool Equals(object obj)
{
return Equals(obj as VisualStudioTaskItem);
}
public bool Equals(VisualStudioTaskItem other)
{
if (this == other)
{
return true;
}
return _checked == other._checked && base.Equals(other);
}
public override int GetHashCode()
{
return Hash.Combine(base.GetHashCode(), _checked ? 1 : 0);
}
protected override int GetChecked(out int pfChecked)
{
pfChecked = _checked ? 1 : 0;
return VSConstants.S_OK;
}
protected override int GetPriority(VSTASKPRIORITY[] ptpPriority)
{
if (ptpPriority != null)
{
ptpPriority[0] = (VSTASKPRIORITY)this.Info.Priority;
}
return VSConstants.S_OK;
}
protected override int PutChecked(int fChecked)
{
_checked = fChecked == 1;
return VSConstants.S_OK;
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor;
using Microsoft.CodeAnalysis.Editor.Implementation.TodoComments;
using Microsoft.CodeAnalysis.Editor.Shared.Tagging;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList
{
[Export(typeof(VisualStudioTodoTaskList))]
internal partial class VisualStudioTodoTaskList : AbstractVisualStudioTaskList, IVsTaskListEvents
{
private readonly Dictionary<object, IVsTaskItem[]> _todoItemMap = new Dictionary<object, IVsTaskItem[]>();
private readonly IOptionService _optionService;
private readonly ITodoListProvider _todoListProvider;
// Batch process updates from the pendingUpdates list.
private readonly object _gate = new object();
private readonly List<ValueTuple<object, ImmutableArray<ITaskItem>>> _pendingUpdates = new List<ValueTuple<object, ImmutableArray<ITaskItem>>>();
private bool _notificationQueued = false;
[ImportingConstructor]
public VisualStudioTodoTaskList(
SVsServiceProvider serviceProvider,
IForegroundNotificationService notificationService,
IOptionService optionService,
ITodoListProvider todoListProvider,
[ImportMany] IEnumerable<Lazy<IAsynchronousOperationListener, FeatureMetadata>> asyncListeners) :
base(serviceProvider, notificationService, FeatureAttribute.TodoCommentList, asyncListeners)
{
// this should be called after all fields are initialized
InitializeTaskList();
_optionService = optionService;
_todoListProvider = todoListProvider;
// we return after initializing task provider since getting option information
// require old task list provider.
if (ErrorListInstalled)
{
return;
}
todoListProvider.TodoListUpdated += OnTodoListUpdated;
}
public override int EnumTaskItems(out IVsEnumTaskItems ppenum)
{
RefreshOrAddTasks(_todoItemMap.Values.SelectMany(x => x).ToArray());
return base.EnumTaskItems(out ppenum);
}
private void OnTodoListUpdated(object sender, TaskListEventArgs args)
{
if (args.TaskListType != PredefinedTaskItemTypes.Todo)
{
return;
}
lock (_gate)
{
_pendingUpdates.Add(ValueTuple.Create(args.Id, args.TaskItems));
if (!_notificationQueued)
{
_notificationQueued = true;
UpdateTodoTaskList();
}
}
}
private void UpdateTodoTaskList()
{
this.NotificationService.RegisterNotification(() =>
{
using (Logger.LogBlock(FunctionId.TaskList_Refresh, CancellationToken.None))
{
using (var listPooledObject = SharedPools.Default<List<IVsTaskItem>>().GetPooledObject())
using (var mapPooledObject = SharedPools.Default<Dictionary<object, ImmutableArray<ITaskItem>>>().GetPooledObject())
{
var removedTasks = listPooledObject.Object;
var addedTasks = mapPooledObject.Object;
lock (_gate)
{
foreach (var args in _pendingUpdates)
{
var key = args.Item1;
var data = args.Item2;
IVsTaskItem[] oldTasks;
if (_todoItemMap.TryGetValue(key, out oldTasks))
{
removedTasks.AddRange(oldTasks);
_todoItemMap.Remove(key);
}
else
{
addedTasks.Remove(key);
}
if (data.Any())
{
addedTasks[key] = data;
}
}
_notificationQueued = false;
_pendingUpdates.Clear();
}
if (removedTasks.Count > 0)
{
RemoveTasks(removedTasks.ToArray());
}
using (var taskList = SharedPools.Default<List<IVsTaskItem>>().GetPooledObject())
{
var newTasks = taskList.Object;
foreach (var addedTaskList in addedTasks)
{
_todoItemMap[addedTaskList.Key] = addedTaskList.Value.Select(i => new VisualStudioTaskItem((TodoTaskItem)i)).ToArray();
newTasks.AddRange(_todoItemMap[addedTaskList.Key]);
}
RefreshOrAddTasks(newTasks.ToArray());
}
}
}
}, TaggerConstants.MediumDelay, this.Listener.BeginAsyncOperation("RefreshTaskList"));
}
public int OnCommentTaskInfoChanged()
{
var tokenInfo = ServiceProvider.GetService(typeof(SVsTaskList)) as IVsCommentTaskInfo;
var commentString = CommentTaskTokenSerializer.GetTaskTokenList(tokenInfo);
var optionSet = _optionService.GetOptions();
var optionValue = optionSet.GetOption(TodoCommentOptions.TokenList);
if (optionValue == commentString)
{
return VSConstants.S_OK;
}
_optionService.SetOptions(optionSet.WithChangedOption(TodoCommentOptions.TokenList, commentString));
return VSConstants.S_OK;
}
internal void TestOnly_Enable()
{
if (!ErrorListInstalled)
{
return;
}
_todoListProvider.TodoListUpdated += OnTodoListUpdated;
}
}
}
......@@ -143,7 +143,6 @@ private void LoadComponents()
this.ComponentModel.GetService<VisualStudioDiagnosticListTable>();
this.ComponentModel.GetService<VisualStudioTodoListTable>();
this.ComponentModel.GetService<VisualStudioTodoTaskList>();
this.ComponentModel.GetService<HACK_ThemeColorFixer>();
this.ComponentModel.GetExtensions<IReferencedSymbolsPresenter>();
this.ComponentModel.GetExtensions<INavigableItemsPresenter>();
......
......@@ -659,17 +659,9 @@
<Compile Include="Implementation\Snippets\SnippetFunctions\AbstractSnippetFunctionGenerateSwitchCases.cs" />
<Compile Include="Implementation\Snippets\SnippetFunctions\AbstractSnippetFunctionSimpleTypeName.cs" />
<Compile Include="Implementation\StandaloneCommandFilter.cs" />
<Compile Include="Implementation\TaskList\AbstractVisualStudioErrorTaskList.cs" />
<Compile Include="Implementation\TaskList\AbstractVisualStudioErrorTaskList.TaskItem.cs" />
<Compile Include="Implementation\TaskList\AbstractVisualStudioTaskList.cs" />
<Compile Include="Implementation\TaskList\AbstractVisualStudioTaskList.IVsTaskProvider.cs" />
<Compile Include="Implementation\TaskList\CommentTaskTokenSerializer.cs" />
<Compile Include="Implementation\TaskList\ExternalErrorDiagnosticUpdateSource.cs" />
<Compile Include="Implementation\TaskList\ProjectExternalErrorReporter.cs" />
<Compile Include="Implementation\TaskList\VisualStudioErrorTaskList.cs" />
<Compile Include="Implementation\TaskList\VisualStudioTaskItemBase.cs" />
<Compile Include="Implementation\TaskList\VisualStudioTodoTaskList.cs" />
<Compile Include="Implementation\TaskList\VisualStudioTodoTaskList.TaskItem.cs" />
<Compile Include="Implementation\Utilities\AbstractNotifyPropertyChanged.cs" />
<Compile Include="Implementation\Utilities\Exceptions.cs" />
<Compile Include="Implementation\Utilities\GlyphExtensions.cs" />
......@@ -784,4 +776,4 @@
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册