Extensions.cs 3.4 KB
Newer Older
P
Pilchie 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
// Copyright (c) Microsoft Open Technologies, Inc.  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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.FindSymbols
{
    internal static partial class Extensions
    {
        public static async Task<IEnumerable<SyntaxToken>> GetConstructorInitializerTokensAsync(this Document document, CancellationToken cancellationToken)
        {
            // model should exist already
            SemanticModel model;
            if (!document.TryGetSemanticModel(out model))
            {
                return Contract.FailWithReturn<IEnumerable<SyntaxToken>>("we should never reach here");
            }

            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
            if (syntaxFacts == null)
            {
                return SpecializedCollections.EmptyEnumerable<SyntaxToken>();
            }

            return FindReferenceCache.GetConstructorInitializerTokens(syntaxFacts, model, root, cancellationToken);
        }

        internal static async Task<IEnumerable<SyntaxToken>> GetIdentifierOrGlobalNamespaceTokensWithTextAsync(
            this Document document, string identifier, CancellationToken cancellationToken)
        {
            // model should exist already
            SemanticModel model;
            if (!document.TryGetSemanticModel(out model))
            {
                return Contract.FailWithReturn<IEnumerable<SyntaxToken>>("we should never reach here");
            }

            // It's very costly to walk an entire tree.  So if the tree is simple and doesn't contain
            // any unicode escapes in it, then we do simple string matching to find the tokens.
            var info = await SyntaxTreeInfo.GetIdentifierInfoAsync(document, cancellationToken).ConfigureAwait(false);
            if (!info.ProbablyContainsIdentifier(identifier))
            {
                return SpecializedCollections.EmptyEnumerable<SyntaxToken>();
            }

            var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
            if (syntaxFacts == null)
            {
                return SpecializedCollections.EmptyEnumerable<SyntaxToken>();
            }

            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
            var version = await document.GetSyntaxVersionAsync(cancellationToken).ConfigureAwait(false);

            SourceText text = null;
            if (!info.ProbablyContainsEscapedIdentifier(identifier))
            {
                text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
            }

            return FindReferenceCache.GetIdentifierOrGlobalNamespaceTokensWithText(syntaxFacts, document, version, model, root, text, identifier, cancellationToken);
        }

        internal static bool TextMatch(this ISyntaxFactsService syntaxFacts, string text1, string text2)
        {
            return syntaxFacts.IsCaseSensitive ? text1 == text2 : string.Equals(text1, text2, StringComparison.OrdinalIgnoreCase);
        }
    }
}