<commit_before>﻿using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using JetBrains.Application;
using JetBrains.Application.Settings;
using JetBrains.ReSharper.ControlFlow.PostfixCompletion.LookupItems;
using JetBrains.ReSharper.ControlFlow.PostfixCompletion.Settings;
using JetBrains.ReSharper.Psi.CSharp.Parsing;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.Util;

namespace JetBrains.ReSharper.ControlFlow.PostfixCompletion
{
  [ShellComponent]
  public class PostfixTemplatesManager
  {
    [NotNull] private readonly IEnumerable<IPostfixTemplateProvider> myTemplateProviders;

    public PostfixTemplatesManager(
      [NotNull] IEnumerable<IPostfixTemplateProvider> templateProviders)
    {
      myTemplateProviders = templateProviders;
      // todo: cache metadata
    }

    [NotNull]
    public IList<PostfixLookupItem> GetAvailableItems(
      [NotNull] ITreeNode node, bool looseChecks, string templateName = null)
    {
      if (node is ICSharpIdentifier || node is ITokenNode)
      {
        var referenceExpression = node.Parent as IReferenceExpression;
        if (referenceExpression != null)
        {
          var expression = referenceExpression.QualifierExpression;
          if (expression != null)
          {
            var replaceRange = referenceExpression.GetDocumentRange().TextRange;
            var canBeStatement = (ExpressionStatementNavigator.GetByExpression(referenceExpression) != null);

            return CollectAvailableTemplates(
              referenceExpression, expression, replaceRange,
              canBeStatement, looseChecks, templateName);
          }
        }

        // handle collisions with C# keyword names:
        // lines.foreach => ExpressionStatement(ReferenceExpression(lines.;Error));ForeachStatement(foreach;Error)
        // todo: prettify this shit

        var statement = node.Parent as ICSharpStatement;
        if (statement != null && statement.FirstChild == node && node.NextSibling is IErrorElement)
        {
          var expressionStatement = statement.PrevSibling as IExpressionStatement;
          if (expressionStatement != null)
          {<commit_msg>Fix 'canBeStatement' for broken trees<commit_after>﻿using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using JetBrains.Application;
using JetBrains.Application.Settings;
using JetBrains.ReSharper.ControlFlow.PostfixCompletion.LookupItems;
using JetBrains.ReSharper.ControlFlow.PostfixCompletion.Settings;
using JetBrains.ReSharper.Psi.CSharp.Parsing;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.Util;

namespace JetBrains.ReSharper.ControlFlow.PostfixCompletion
{
  [ShellComponent]
  public class PostfixTemplatesManager
  {
    [NotNull] private readonly IEnumerable<IPostfixTemplateProvider> myTemplateProviders;

    public PostfixTemplatesManager(
      [NotNull] IEnumerable<IPostfixTemplateProvider> templateProviders)
    {
      myTemplateProviders = templateProviders;
      // todo: cache metadata
    }

    [NotNull]
    public IList<PostfixLookupItem> GetAvailableItems(
      [NotNull] ITreeNode node, bool looseChecks, string templateName = null)
    {
      if (node is ICSharpIdentifier || node is ITokenNode)
      {
        var referenceExpression = node.Parent as IReferenceExpression;
        if (referenceExpression != null)
        {
          var expression = referenceExpression.QualifierExpression;
          if (expression != null)
          {
            var replaceRange = referenceExpression.GetDocumentRange().TextRange;
            var canBeStatement = (ExpressionStatementNavigator.GetByExpression(referenceExpression) != null);
            if (!canBeStatement)
            {
              var containingStatement = referenceExpression.GetContainingNode<ICSharpStatement>();
              if (containingStatement != null)
              {
                var a = referenceExpression.GetTreeStartOffset();
                var b = containingStatement.GetTreeStartOffset();
                if (a == b)
                  canBeStatement = true;
              }
            }

            return CollectAvailableTemplates(
              referenceExpression, expression, replaceRange,
              canBeStatement, looseChecks, templateName);
          }
        }

        // handle collisions with C# keyword names:
        // lines.foreach => ExpressionStatement(ReferenceExpression(lines.;Error));ForeachStatement(foreach;Error)
        // todo: prettify this shit

        var statement = node.Parent as ICSharpStatement;
        if (statement != null && statement.FirstChild == node && node.NextSibling is IErrorElement)
        {
          var expressionStatement = statement.PrevSibling as IExpressionStatement;
          if (expressionStatement != null)
          {
{'fraction_non_alphanumeric': 0.0768916155419223, 'fraction_numerical': 0.0, 'mean_word_length': 3.127426160337553, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 12, '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': '3797406', 'n_tokens_mistral': 1246, 'n_tokens_neox': 1223, 'n_words': 271}