<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.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.CSharp.UseIndexOperator
{
    using static Helpers;

    /// <summary>
    /// Analyzer that looks for several variants of code like `s.Slice(start, end - start)` and
    /// offers to update to `s[start..end]`.  In order to convert, the type being called on needs a
    /// slice-like method that takes two ints, and returns an instance of the same type. It also
    /// needs a Length/Count property, as well as an indexer that takes a System.Range instance.
    ///
    /// It is assumed that if the type follows this shape that it is well behaved and that this
    /// transformation will preserve semantics.  If this assumption is not good in practice, we
    /// could always limit the feature to only work on a whitelist of known safe types.
    /// </summary>
    [DiagnosticAnalyzer(LanguageNames.CSharp), Shared]
    internal partial class CSharpUseRangeOperatorDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer
    {
        public const string StartFromEnd = nameof(StartFromEnd);
        public const string EndFromEnd = nameof(EndFromEnd);
        public const string OmitStart = nameof(OmitStart);
        public const string OmitEnd = nameof(OmitEnd);

        public CSharpUseRangeOperatorDiagnosticAnalyzer() 
            : base(IDEDiagnosticIds.UseRangeOperatorDiagnosticId,
                   new LocalizableResourceString(nameof(FeaturesResources.Use_range_operator), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
                   new LocalizableResourceString(nameof(FeaturesResources._0_can_be_simplified), FeaturesResources.ResourceManager, typeof(FeaturesResources)))
        {
        }

        /// <summary>
        /// Look for methods like "ContainingType Slice(int start, int length)".
        /// </summary>
        private static bool IsSliceLikeMethod(IMethodSymbol method)
            => IsPublicInstance(method) &&
               method.Parameters.Length == 2 &&
               (method.Parameters[0].Name == "start" || method.Parameters[0].Name == "startIndex") &&
               (method.Parameters[1].Name == "count" || method.Parameters[1].Name == "length") &&
               method.ContainingType.Equals(method.ReturnType);<commit_msg>Comments.<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.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.CSharp.UseIndexOperator
{
    using static Helpers;

    /// <summary>
    /// Analyzer that looks for several variants of code like `s.Slice(start, end - start)` and
    /// offers to update to `s[start..end]`.  In order to convert, the type being called on needs a
    /// slice-like method that takes two ints, and returns an instance of the same type. It also
    /// needs a Length/Count property, as well as an indexer that takes a System.Range instance.
    ///
    /// It is assumed that if the type follows this shape that it is well behaved and that this
    /// transformation will preserve semantics.  If this assumption is not good in practice, we
    /// could always limit the feature to only work on a whitelist of known safe types.
    /// </summary>
    [DiagnosticAnalyzer(LanguageNames.CSharp), Shared]
    internal partial class CSharpUseRangeOperatorDiagnosticAnalyzer : AbstractCodeStyleDiagnosticAnalyzer
    {
        // Flags to indicate if we should generate 'val' or '^val' for the start or end range values
        public const string StartFromEnd = nameof(StartFromEnd);
        public const string EndFromEnd = nameof(EndFromEnd);

        // Flags to indicate if we should just omit the start/end value of the range entirely.
        public const string OmitStart = nameof(OmitStart);
        public const string OmitEnd = nameof(OmitEnd);

        public CSharpUseRangeOperatorDiagnosticAnalyzer() 
            : base(IDEDiagnosticIds.UseRangeOperatorDiagnosticId,
                   new LocalizableResourceString(nameof(FeaturesResources.Use_range_operator), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
                   new LocalizableResourceString(nameof(FeaturesResources._0_can_be_simplified), FeaturesResources.ResourceManager, typeof(FeaturesResources)))
        {
        }

        /// <summary>
        /// Look for methods like "ContainingType Slice(int start, int length)".
        /// </summary>
        private static bool IsSliceLikeMethod(IMethodSymbol method)
            => IsPublicInstance(method) &&
               method.Parameters.Length == 2 &&
               (method.Parameters[0].Name == "start" || method.Parameters[0].Name == "startIndex") &&
               (method.Parameters[1].Name == "count" || method.Parameters[1].Name == "length") &&
               method.ContainingType.Equals(method.ReturnType);
{'fraction_non_alphanumeric': 0.08831353076786665, 'fraction_numerical': 0.0028373825146302536, 'mean_word_length': 3.275966641394996, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, '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': '5048253', 'n_tokens_mistral': 1436, 'n_tokens_neox': 1396, 'n_words': 465}