// 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.Collections.Immutable; using System.ComponentModel.Composition; using System.Globalization; using System.Threading; using Microsoft.CodeAnalysis.TodoComments; namespace Microsoft.CodeAnalysis.Editor.Implementation.TodoComments { /// /// provide comment tokens to scan /// /// we use this indirection so that we can get different tokens based on host /// [Export] internal class TodoCommentTokens { [ImportingConstructor] public TodoCommentTokens() { } private ImmutableArray Parse(string data) { if (string.IsNullOrWhiteSpace(data)) { return ImmutableArray.Empty; } var tuples = data.Split('|'); var result = new List(tuples.Length); foreach (var tuple in tuples) { if (string.IsNullOrWhiteSpace(tuple)) { continue; } var pair = tuple.Split(':'); if (pair.Length != 2 || string.IsNullOrWhiteSpace(pair[0])) { continue; } if (!int.TryParse(pair[1], NumberStyles.None, CultureInfo.InvariantCulture, out var priority)) { continue; } result.Add(new TodoCommentDescriptor(pair[0].Trim(), priority)); } return result.ToImmutableArray(); } private class TokenInfo { internal readonly string OptionText; internal readonly ImmutableArray Tokens; public TokenInfo(string optionText, ImmutableArray tokens) { this.OptionText = optionText; this.Tokens = tokens; } } private TokenInfo _lastTokenInfo; public ImmutableArray GetTokens(Document document, CancellationToken cancellationToken) { var optionText = document.Project.Solution.Options.GetOption(TodoCommentOptions.TokenList); var lastInfo = _lastTokenInfo; if (lastInfo != null && lastInfo.OptionText == optionText) { return lastInfo.Tokens; } var tokens = Parse(optionText); System.Threading.Interlocked.CompareExchange(ref _lastTokenInfo, new TokenInfo(optionText, tokens), lastInfo); return tokens; } } }