<commit_before>﻿// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.Implementation.Debugging;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.VisualStudio.LanguageServices.CSharp.Debugging
{
    internal static class DataTipInfoGetter
    {
        internal static async Task<DebugDataTipInfo> GetInfoAsync(Document document, int position, CancellationToken cancellationToken)
        {
            try
            {
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                var token = root.FindToken(position);

                var expression = token.Parent as ExpressionSyntax;
                if (expression == null)
                {
                    return token.IsKind(SyntaxKind.IdentifierToken)
                        ? new DebugDataTipInfo(token.Span, text: null)
                        : default;
                }

                if (expression.IsAnyLiteralExpression())
                {
                    // If the user hovers over a literal, give them a DataTip for the type of the
                    // literal they're hovering over.
                    // Partial semantics should always be sufficient because the (unconverted) type
                    // of a literal can always easily be determined.
                    var semanticModel = await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false);<commit_msg>Harden against null in GetInfoAsync (#21855)<commit_after>﻿// 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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.Implementation.Debugging;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.VisualStudio.LanguageServices.CSharp.Debugging
{
    internal static class DataTipInfoGetter
    {
        internal static async Task<DebugDataTipInfo> GetInfoAsync(Document document, int position, CancellationToken cancellationToken)
        {
            try
            {
                var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                if (root == null)
                {
                    return default;
                }

                var token = root.FindToken(position);

                var expression = token.Parent as ExpressionSyntax;
                if (expression == null)
                {
                    return token.IsKind(SyntaxKind.IdentifierToken)
                        ? new DebugDataTipInfo(token.Span, text: null)
                        : default;
                }

                if (expression.IsAnyLiteralExpression())
                {
                    // If the user hovers over a literal, give them a DataTip for the type of the
                    // literal they're hovering over.
                    // Partial semantics should always be sufficient because the (unconverted) type
                    // of a literal can always easily be determined.
                    var semanticModel = await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false);
{'fraction_non_alphanumeric': 0.06602336211274759, 'fraction_numerical': 0.0022854240731335703, 'mean_word_length': 2.3240506329113924, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2012335', 'n_tokens_mistral': 928, 'n_tokens_neox': 879, 'n_words': 265}