All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.plugins.groovy.dsl.DslPointcut Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition groovy-psi library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2014 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.dsl;

import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.dsl.toplevel.ClassContextFilter;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.ClassUtil;

import java.util.*;

/**
 * @author peter
 */
@SuppressWarnings("UnusedDeclaration")
public abstract class DslPointcut {
  public static final DslPointcut UNKNOWN = new DslPointcut() {

    @Override
    List matches(Object src, ProcessingContext context) {
      return Collections.emptyList();
    }

    @Override
    boolean operatesOn(Class c) {
      return true;
    }
  };
  public static Key> BOUND = Key.create("gdsl.bound");

  @Nullable
  abstract List matches(T src, ProcessingContext context);

  abstract boolean operatesOn(Class c);

  public DslPointcut and(final DslPointcut next) {
    final DslPointcut first = this;
    return new DslPointcut() {
      @Override
      List matches(T src, ProcessingContext context) {
        final List vs1 = first.matches(src, context);
        if (vs1 == null) return null;

        final List vs2 = next.matches(src, context);
        if (vs2 == null) return null;

        final List result = new ArrayList(vs1);
        result.retainAll(new HashSet(vs2));
        return result;
      }

      @Override
      boolean operatesOn(Class c) {
        return first.operatesOn(c) && next.operatesOn(c);
      }
    };
  }

  public DslPointcut or(final DslPointcut next) {
    final DslPointcut first = this;
    return new DslPointcut() {
      @Override
      List matches(T src, ProcessingContext context) {
        final List vs1 = first.matches(src, context);
        final List vs2 = next.matches(src, context);

        if (vs1 == null && vs2 == null) return null;

        final Set result = new LinkedHashSet();
        if (vs1 != null) {
          result.addAll(vs1);
        }
        if (vs2 != null) {
          result.addAll(vs2);
        }
        return new ArrayList(result);
      }

      @Override
      boolean operatesOn(Class c) {
        return first.operatesOn(c) && next.operatesOn(c);
      }
    };
  }
  public DslPointcut bitwiseNegate() {
    final DslPointcut base = this;
    return new DslPointcut() {
      @Override
      List matches(T src, ProcessingContext context) {
        return base.matches(src, context) == null ? Collections.emptyList() : null;
      }

      @Override
      boolean operatesOn(Class c) {
        return base.operatesOn(c);
      }
    };
  }


  public static DslPointcut subType(final Object arg) {
    return new DslPointcut() {

      @Override
      List matches(GdslType src, ProcessingContext context) {
        final PsiFile placeFile = context.get(GdslUtil.INITIAL_CONTEXT).getPlaceFile();
        if (ClassContextFilter.isSubtype(src.psiType, placeFile, (String)arg)) {
          return Arrays.asList(src);
        }
        return null;
      }

      @Override
      boolean operatesOn(Class c) {
        return GdslType.class == c;
      }
    };

  }

  public static DslPointcut currentType(final Object arg) {
    final DslPointcut inner;
    if (arg instanceof String) {
      inner = subType(arg);
    } else {
      inner = (DslPointcut)arg;
      assert inner.operatesOn(GdslType.class) : "The argument to currentType should be a pointcut working with types, e.g. subType";
    }

    return new DslPointcut() {

      @Override
      List matches(GroovyClassDescriptor src, ProcessingContext context) {
        final GdslType currentType = new GdslType(ClassUtil.findPsiType(src, context));
        if (inner.matches(currentType, context) != null) {
          return Arrays.asList(currentType);
        }
        return null;
      }

      @Override
      boolean operatesOn(Class c) {
        return GroovyClassDescriptor.class == c;
      }
    };
  }

  public static DslPointcut enclosingType(final Object arg) {
    return new DslPointcut() {
      @Override
      List matches(GroovyClassDescriptor src, ProcessingContext context) {
        List result = new ArrayList();
        PsiElement place = src.getPlace();
        while (true) {
          final PsiClass cls = PsiTreeUtil.getContextOfType(place, PsiClass.class);
          if (cls == null) {
            break;
          }
          if (arg.equals(cls.getQualifiedName())) {
            result.add(new GdslType(JavaPsiFacade.getElementFactory(cls.getProject()).createType(cls)));
          }
          place = cls;
        }
        return result.isEmpty() ? null : result;
      }

      @Override
      boolean operatesOn(Class c) {
        return GroovyClassDescriptor.class == c;
      }
    };
  }

  public static DslPointcut name(final Object arg) {
    return new DslPointcut() {
      @Override
      List matches(Object src, ProcessingContext context) {
        if (src instanceof GdslType) {
          return arg.equals(((GdslType)src).getName()) ? Arrays.asList((String)arg) : null;
        }
        if (src instanceof GdslMethod) {
          return arg.equals(((GdslMethod)src).getName()) ? Arrays.asList((String)arg) : null;
        }
        return Collections.emptyList();
      }

      @Override
      boolean operatesOn(Class c) {
        return c == GdslType.class || c == GdslMethod.class;
      }
    };

  }

  public static DslPointcut enclosingMethod(final Object arg) {
    final DslPointcut inner;
    if (arg instanceof String) {
      inner = name(arg);
    } else {
      inner = (DslPointcut)arg;
      assert inner.operatesOn(GdslMethod.class) : "The argument to enclosingMethod should be a pointcut working with methods, e.g. name";
    }

    return new DslPointcut() {
      @Override
      List matches(GroovyClassDescriptor src, ProcessingContext context) {
        List result = new ArrayList();
        PsiElement place = src.getPlace();
        while (true) {
          final PsiMethod method = PsiTreeUtil.getContextOfType(place, PsiMethod.class);
          if (method == null) {
            break;
          }
          final GdslMethod wrapper = new GdslMethod(method);
          if (inner.matches(wrapper, context) != null) {
            result.add(wrapper);
          }
          place = method;
        }
        return result.isEmpty() ? null : result;
      }

      @Override
      boolean operatesOn(Class c) {
        return GroovyClassDescriptor.class == c;
      }
    };
  }

  public static DslPointcut bind(final Object arg) {
    assert arg instanceof Map;
    assert ((Map)arg).size() == 1;
    final String name = (String)((Map)arg).keySet().iterator().next();
    final DslPointcut pct = (DslPointcut)((Map)arg).values().iterator().next();

    return new DslPointcut() {
      @Override
      List matches(Object src, ProcessingContext context) {
        final List result = pct.matches(src, context);
        if (result != null) {
          Map map = context.get(BOUND);
          if (map == null) {
            context.put(BOUND, map = new HashMap());
          }
          map.put(name, result);
        }
        return result;
      }

      @Override
      boolean operatesOn(Class c) {
        return pct.operatesOn(c);
      }
    };
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy