<commit_before>package org.jetbrains.plugins.groovy.codeInspection.noReturnMethod;

import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ControlFlowUtil;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;

/**
 * @author ven
 */
public class MissingReturnInspection extends LocalInspectionTool {
  @Nls
  @NotNull
  public String getGroupDisplayName() {
    return GroovyInspectionBundle.message("groovy.dfa.issues");
  }

  @Nls
  @NotNull
  public String getDisplayName() {
    return GroovyInspectionBundle.message("no.return.display.name");
  }

  @NotNull
  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder problemsHolder, boolean onTheFly) {
    return new GroovyPsiElementVisitor(new GroovyElementVisitor() {
      public void visitClosure(GrClosableBlock closure) {
        check(closure, problemsHolder);
        super.visitClosure(closure);
      }

      public void visitMethod(GrMethod method) {
        final GrOpenBlock block = method.getBlock();
        if (block != null) {
          check(block, problemsHolder);
        }
        super.visitMethod(method);
      }
    });

  }

  private void check(GrCodeBlock block, ProblemsHolder holder) {
    GrStatement[] statements = block.getStatements();
    if (statements.length > 0 && !(statements[statements.length - 1] instanceof GrExpression)) {
      if (hasValueReturns(block)) {
        Instruction[] flow = block.getControlFlow();
        if (!ControlFlowUtil.alwaysReturns(flow)) {
          final PsiElement lastChild = block.getLastChild();
          if (lastChild == null || !lastChild.isValid() || !lastChild.isPhysical()) {
            return;
          }
          holder.registerProblem(lastChild, GroovyInspectionBundle.message("no.return.message"));
        }
      }
    }
  }

  private boolean hasValueReturns(GrCodeBlock block) {
    class Visitor extends GroovyRecursiveElementVisitor {
      private boolean myFound = false;

      public boolean isFound() {
        return myFound;
      }

      public void visitReturnStatement(GrReturnStatement returnStatement) {
        if (returnStatement.getReturnValue() != null) myFound = true;
      }

      public void visitElement(GroovyPsiElement element) {
        if (!myFound) {<commit_msg>GRVY-1728 et al.<commit_after>package org.jetbrains.plugins.groovy.codeInspection.noReturnMethod;

import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ControlFlowUtil;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;

/**
 * @author ven
 */
public class MissingReturnInspection extends LocalInspectionTool {
  @Nls
  @NotNull
  public String getGroupDisplayName() {
    return GroovyInspectionBundle.message("groovy.dfa.issues");
  }

  @Nls
  @NotNull
  public String getDisplayName() {
    return GroovyInspectionBundle.message("no.return.display.name");
  }

  @NotNull
  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder problemsHolder, boolean onTheFly) {
    return new GroovyPsiElementVisitor(new GroovyElementVisitor() {
      public void visitClosure(GrClosableBlock closure) {
        check(closure, problemsHolder);
        super.visitClosure(closure);
      }

      public void visitMethod(GrMethod method) {
        final GrOpenBlock block = method.getBlock();
        if (block != null) {
          check(block, problemsHolder);
        }
        super.visitMethod(method);
      }
    });

  }

  private void check(GrCodeBlock block, ProblemsHolder holder) {
    GrStatement[] statements = block.getStatements();
    if (statements.length > 0 && !(statements[statements.length - 1] instanceof GrExpression)) {
      if (hasValueReturns(block)) {
        Instruction[] flow = block.getControlFlow();
        if (!ControlFlowUtil.alwaysReturns(flow)) {
          final PsiElement lastChild = block.getLastChild();
          if (lastChild == null) return;
          TextRange range = lastChild.getTextRange();
          if (!lastChild.isValid() || !lastChild.isPhysical() || range.getStartOffset() >= range.getEndOffset()) {
            return;
          }
          holder.registerProblem(lastChild, GroovyInspectionBundle.message("no.return.message"));
        }
      }
    }
  }

  private boolean hasValueReturns(GrCodeBlock block) {
    class Visitor extends GroovyRecursiveElementVisitor {
      private boolean myFound = false;

      public boolean isFound() {
        return myFound;
      }

      public void visitReturnStatement(GrReturnStatement returnStatement) {
        if (returnStatement.getReturnValue() != null) myFound = true;
      }

      public void visitElement(GroovyPsiElement element) {
        if (!myFound) {
{'fraction_non_alphanumeric': 0.10293912801225798, 'fraction_numerical': 0.0011143613316617913, 'mean_word_length': 4.146953405017921, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, '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': '4633145', 'n_tokens_mistral': 2243, 'n_tokens_neox': 2074, 'n_words': 343}