<commit_before>/*
 * Copyright 2000-2017 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jetbrains.plugins.groovy.transformations.impl;

import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.PsiClassType.ClassResolveResult;
import com.intellij.psi.impl.compiled.ClsClassImpl;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitField;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod;
import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil;
import org.jetbrains.plugins.groovy.transformations.AstTransformationSupport;
import org.jetbrains.plugins.groovy.transformations.TransformationContext;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Set;

public class TraitTransformationSupport implements AstTransformationSupport {

  @Override
  public void applyTransformation(@NotNull TransformationContext context) {
    if (context.getCodeClass().isInterface() && !context.getCodeClass().isTrait()) return;

    if (context.getCodeClass().isTrait()) {
      for (GrField field : context.getCodeClass().getCodeFields()) {
        context.addField(new GrTraitField(field, context.getCodeClass(), PsiSubstitutor.EMPTY));
      }
    }

    process(context, (trait, substitutor) -> {
      if (trait instanceof GrTypeDefinition) {
        for (PsiMethod method : trait.getMethods()) {
          if (!method.getModifierList().hasExplicitModifier(PsiModifier.ABSTRACT) &&
              !method.getModifierList().hasExplicitModifier(PsiModifier.PRIVATE)) {
            context.addMethods(getExpandingMethods(context.getCodeClass(), method, substitutor));
          }
        }
        for (GrField field : ((GrTypeDefinition)trait).getCodeFields()) {
          context.addField(new GrTraitField(field, context.getCodeClass(), substitutor));
        }
      }
      else if (trait instanceof ClsClassImpl) {
        for (PsiMethod method : GrTraitUtil.getCompiledTraitConcreteMethods((ClsClassImpl)trait)) {
          context.addMethods(getExpandingMethods(context.getCodeClass(), method, substitutor));
        }
        for (GrField field : GrTraitUtil.getCompiledTraitFields((ClsClassImpl)trait)) {
          context.addField(new GrTraitField(field, context.getCodeClass(), substitutor));
        }
      }
    });
  }

  private static void process(@NotNull TransformationContext context, @NotNull PairConsumer<PsiClass, PsiSubstitutor> consumer) {
    Deque<Pair<PsiClass, PsiSubstitutor>> stack = new ArrayDeque<>();

    for (PsiClassType superType : context.getSuperTypes()) {
      ClassResolveResult result = superType.resolveGenerics();
      PsiClass superClass = result.getElement();
      if (superClass == null) continue;
      stack.push(Pair.create(superClass, result.getSubstitutor()));
    }

    Set<PsiClass> visited = ContainerUtil.newHashSet();

    while (!stack.isEmpty()) {
      Pair<PsiClass, PsiSubstitutor> current = stack.pop();
      PsiClass currentClass = current.first;
      PsiSubstitutor currentSubstitutor = current.second;
      if (!visited.add(currentClass)) continue;
      if (GrTraitUtil.isTrait(currentClass)) {
        consumer.consume(currentClass, currentSubstitutor);
      }
      for (PsiClass superClass : currentClass.getSupers()) {
        PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, currentClass, currentSubstitutor);
        stack.push(Pair.create(superClass, superSubstitutor));
      }
    }
  }<commit_msg>[groovy] don't apply trait transformation when trait doesn't have qualified name<commit_after>// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.plugins.groovy.transformations.impl;

import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.PsiClassType.ClassResolveResult;
import com.intellij.psi.impl.compiled.ClsClassImpl;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitField;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod;
import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil;
import org.jetbrains.plugins.groovy.transformations.AstTransformationSupport;
import org.jetbrains.plugins.groovy.transformations.TransformationContext;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Set;

public class TraitTransformationSupport implements AstTransformationSupport {

  @Override
  public void applyTransformation(@NotNull TransformationContext context) {
    final GrTypeDefinition codeClass = context.getCodeClass();
    if (codeClass.isInterface() && !codeClass.isTrait()) return;

    if (codeClass.isTrait() && codeClass.getQualifiedName() != null) {
      for (GrField field : codeClass.getCodeFields()) {
        context.addField(new GrTraitField(field, codeClass, PsiSubstitutor.EMPTY));
      }
    }

    process(context, (trait, substitutor) -> {
      if (trait instanceof GrTypeDefinition) {
        for (PsiMethod method : trait.getMethods()) {
          if (!method.getModifierList().hasExplicitModifier(PsiModifier.ABSTRACT) &&
              !method.getModifierList().hasExplicitModifier(PsiModifier.PRIVATE)) {
            context.addMethods(getExpandingMethods(codeClass, method, substitutor));
          }
        }
        for (GrField field : ((GrTypeDefinition)trait).getCodeFields()) {
          context.addField(new GrTraitField(field, codeClass, substitutor));
        }
      }
      else if (trait instanceof ClsClassImpl) {
        for (PsiMethod method : GrTraitUtil.getCompiledTraitConcreteMethods((ClsClassImpl)trait)) {
          context.addMethods(getExpandingMethods(codeClass, method, substitutor));
        }
        for (GrField field : GrTraitUtil.getCompiledTraitFields((ClsClassImpl)trait)) {
          context.addField(new GrTraitField(field, codeClass, substitutor));
        }
      }
    });
  }

  private static void process(@NotNull TransformationContext context, @NotNull PairConsumer<PsiClass, PsiSubstitutor> consumer) {
    Deque<Pair<PsiClass, PsiSubstitutor>> stack = new ArrayDeque<>();

    for (PsiClassType superType : context.getSuperTypes()) {
      ClassResolveResult result = superType.resolveGenerics();
      PsiClass superClass = result.getElement();
      if (superClass == null) continue;
      stack.push(Pair.create(superClass, result.getSubstitutor()));
    }

    Set<PsiClass> visited = ContainerUtil.newHashSet();

    while (!stack.isEmpty()) {
      Pair<PsiClass, PsiSubstitutor> current = stack.pop();
      PsiClass currentClass = current.first;
      PsiSubstitutor currentSubstitutor = current.second;
      if (!visited.add(currentClass)) continue;
      if (GrTraitUtil.isTrait(currentClass)) {
        consumer.consume(currentClass, currentSubstitutor);
      }
      for (PsiClass superClass : currentClass.getSupers()) {
        PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, currentClass, currentSubstitutor);
        stack.push(Pair.create(superClass, superSubstitutor));
      }
    }
  }
{'fraction_non_alphanumeric': 0.106544901065449, 'fraction_numerical': 0.0025758107949888772, 'mean_word_length': 4.282622139764997, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, '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': '3878967', 'n_tokens_mistral': 2584, 'n_tokens_neox': 2464, 'n_words': 476}