<commit_before>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.VisualStudio.Text.Tagging;
using CSharp = Microsoft.CodeAnalysis.CSharp;
using VB = Microsoft.CodeAnalysis.VisualBasic;
using System.Threading.Tasks;

namespace RoslynColorizer {

  [Export(typeof(ITaggerProvider))]
  [ContentType("CSharp")]
  [ContentType("Basic")]
  [TagType(typeof(IClassificationTag))]
  internal class RoslynColorizerProvider : ITaggerProvider {
    [Import]
    internal IClassificationTypeRegistryService ClassificationRegistry = null; // Set via MEF

    public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag {
      return (ITagger<T>)new RoslynColorizer(buffer, ClassificationRegistry);
    }
  }

  class RoslynColorizer : ITagger<IClassificationTag> {
    private IClassificationType parameterType;
    private IClassificationType fieldType;
    private ITextBuffer theBuffer;
#pragma warning disable CS0067
    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
#pragma warning restore CS0067

    internal RoslynColorizer(ITextBuffer buffer, IClassificationTypeRegistryService registry) {
      theBuffer = buffer;
      parameterType = registry.GetClassificationType(Constants.ParameterFormat);
      fieldType = registry.GetClassificationType(Constants.FieldFormat);
    }

    public IEnumerable<ITagSpan<IClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans) {
      if ( spans.Count == 0 ) {
        return Enumerable.Empty<ITagSpan<IClassificationTag>>();
      }
      // this makes me feel dirty, but otherwise it will not
      // work reliably, as TryGetSemanticModel() often will return false
      // should make this into a completely async process somehow
      var task = RoslynDocument.Resolve(theBuffer, spans[0].Snapshot);
      task.Wait();
      if ( task.IsFaulted ) {
        // TODO: report this to someone.
        return Enumerable.Empty<ITagSpan<IClassificationTag>>();
      }
      return GetTagsImpl(task.Result, spans);
    }

    private IEnumerable<ITagSpan<IClassificationTag>> GetTagsImpl(
          RoslynDocument doc,
          NormalizedSnapshotSpanCollection spans) {
      var snapshot = spans[0].Snapshot;

      IEnumerable<ClassifiedSpan> identifiers = 
        GetIdentifiersInSpans(doc.Workspace, doc.SemanticModel, spans);

      foreach ( var id in identifiers ) {
        var node = doc.SyntaxRoot.FindNode(id.TextSpan);
        var symbol = doc.SemanticModel.GetSymbolInfo(GetExpression(node)).Symbol;
        if ( symbol == null ) {
          continue;
        }
        switch ( symbol.Kind ) {
          case SymbolKind.Parameter:
            yield return id.TextSpan.ToTagSpan(snapshot, parameterType);
            break;
          case SymbolKind.Field:
            yield return id.TextSpan.ToTagSpan(snapshot, fieldType);
            break;
        }
      }
    }

    private SyntaxNode GetExpression(SyntaxNode node) {
      if ( node.CSharpKind() == CSharp.SyntaxKind.Argument ) {
        return ((CSharp.Syntax.ArgumentSyntax)node).Expression;
      } else if ( node.VBKind() == VB.SyntaxKind.SimpleArgument ) {
        return ((VB.Syntax.SimpleArgumentSyntax)node).Expression;
      }
      return node;
    }

    private IEnumerable<ClassifiedSpan> GetIdentifiersInSpans(
          Workspace workspace, SemanticModel model,
          NormalizedSnapshotSpanCollection spans) {
      var comparer = StringComparer.InvariantCultureIgnoreCase;<commit_msg>Ignore enum members when highlighting fields<commit_after>﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.VisualStudio.Text.Tagging;
using CSharp = Microsoft.CodeAnalysis.CSharp;
using VB = Microsoft.CodeAnalysis.VisualBasic;
using System.Threading.Tasks;

namespace RoslynColorizer {

  [Export(typeof(ITaggerProvider))]
  [ContentType("CSharp")]
  [ContentType("Basic")]
  [TagType(typeof(IClassificationTag))]
  internal class RoslynColorizerProvider : ITaggerProvider {
    [Import]
    internal IClassificationTypeRegistryService ClassificationRegistry = null; // Set via MEF

    public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag {
      return (ITagger<T>)new RoslynColorizer(buffer, ClassificationRegistry);
    }
  }

  class RoslynColorizer : ITagger<IClassificationTag> {
    private IClassificationType parameterType;
    private IClassificationType fieldType;
    private ITextBuffer theBuffer;
#pragma warning disable CS0067
    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
#pragma warning restore CS0067

    internal RoslynColorizer(ITextBuffer buffer, IClassificationTypeRegistryService registry) {
      theBuffer = buffer;
      parameterType = registry.GetClassificationType(Constants.ParameterFormat);
      fieldType = registry.GetClassificationType(Constants.FieldFormat);
    }

    public IEnumerable<ITagSpan<IClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans) {
      if ( spans.Count == 0 ) {
        return Enumerable.Empty<ITagSpan<IClassificationTag>>();
      }
      // this makes me feel dirty, but otherwise it will not
      // work reliably, as TryGetSemanticModel() often will return false
      // should make this into a completely async process somehow
      var task = RoslynDocument.Resolve(theBuffer, spans[0].Snapshot);
      task.Wait();
      if ( task.IsFaulted ) {
        // TODO: report this to someone.
        return Enumerable.Empty<ITagSpan<IClassificationTag>>();
      }
      return GetTagsImpl(task.Result, spans);
    }

    private IEnumerable<ITagSpan<IClassificationTag>> GetTagsImpl(
          RoslynDocument doc,
          NormalizedSnapshotSpanCollection spans) {
      var snapshot = spans[0].Snapshot;

      IEnumerable<ClassifiedSpan> identifiers = 
        GetIdentifiersInSpans(doc.Workspace, doc.SemanticModel, spans);

      foreach ( var id in identifiers ) {
        var node = doc.SyntaxRoot.FindNode(id.TextSpan);
        var symbol = doc.SemanticModel.GetSymbolInfo(GetExpression(node)).Symbol;
        if ( symbol == null ) {
          continue;
        }
        switch ( symbol.Kind ) {
          case SymbolKind.Parameter:
            yield return id.TextSpan.ToTagSpan(snapshot, parameterType);
            break;
          case SymbolKind.Field:
            if ( symbol.ContainingType.TypeKind != TypeKind.Enum ) {
              yield return id.TextSpan.ToTagSpan(snapshot, fieldType);
            }
            break;
        }
      }
    }

    private SyntaxNode GetExpression(SyntaxNode node) {
      if ( node.CSharpKind() == CSharp.SyntaxKind.Argument ) {
        return ((CSharp.Syntax.ArgumentSyntax)node).Expression;
      } else if ( node.VBKind() == VB.SyntaxKind.SimpleArgument ) {
        return ((VB.Syntax.SimpleArgumentSyntax)node).Expression;
      }
      return node;
    }

    private IEnumerable<ClassifiedSpan> GetIdentifiersInSpans(
          Workspace workspace, SemanticModel model,
          NormalizedSnapshotSpanCollection spans) {
      var comparer = StringComparer.InvariantCultureIgnoreCase;
{'fraction_non_alphanumeric': 0.08580036678019387, 'fraction_numerical': 0.002881844380403458, 'mean_word_length': 3.5800839832033593, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, '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': '6626224', 'n_tokens_mistral': 2081, 'n_tokens_neox': 2002, 'n_words': 451}