/platform/platform-api/src/com/intellij/patterns/TreeElementPattern.java

https://bitbucket.org/nbargnesi/idea
Java | 225 lines | 178 code | 25 blank | 22 comment | 33 complexity | 643da1c03875ae79932f7b4117f7213d MD5 | raw file
  1. /*
  2. * Copyright 2000-2009 JetBrains s.r.o.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.intellij.patterns;
  17. import com.intellij.util.PairProcessor;
  18. import com.intellij.util.ProcessingContext;
  19. import org.jetbrains.annotations.NotNull;
  20. import org.jetbrains.annotations.Nullable;
  21. import java.util.Arrays;
  22. import java.util.Collection;
  23. /**
  24. * @author peter
  25. */
  26. public abstract class TreeElementPattern<ParentType, T extends ParentType, Self extends TreeElementPattern<ParentType, T, Self>>
  27. extends ObjectPattern<T, Self> {
  28. protected TreeElementPattern(@NotNull final InitialPatternCondition<T> condition) {
  29. super(condition);
  30. }
  31. protected TreeElementPattern(final Class<T> aClass) {
  32. super(aClass);
  33. }
  34. @Nullable
  35. protected abstract ParentType getParent(@NotNull ParentType parentType);
  36. protected abstract ParentType[] getChildren(@NotNull final ParentType parentType);
  37. public Self withParents(@NotNull final Class<? extends ParentType>... types) {
  38. return with(new PatternCondition<T>("withParents") {
  39. @Override
  40. public boolean accepts(@NotNull T t, ProcessingContext context) {
  41. ParentType current = getParent(t);
  42. for (Class<? extends ParentType> type : types) {
  43. if (current == null || !type.isInstance(current)) {
  44. return false;
  45. }
  46. current = getParent(current);
  47. }
  48. return true;
  49. }
  50. });
  51. }
  52. public Self withParent(@NotNull final Class<? extends ParentType> type) {
  53. return withParent(StandardPatterns.instanceOf(type));
  54. }
  55. public Self withParent(@NotNull final ElementPattern<? extends ParentType> pattern) {
  56. return withSuperParent(1, pattern);
  57. }
  58. public Self withChild(@NotNull final ElementPattern<? extends ParentType> pattern) {
  59. return withChildren(StandardPatterns.<ParentType>collection().atLeastOne(pattern));
  60. }
  61. public Self withFirstChild(@NotNull final ElementPattern<? extends ParentType> pattern) {
  62. return withChildren(StandardPatterns.<ParentType>collection().first(pattern));
  63. }
  64. public Self withLastChild(@NotNull final ElementPattern<? extends ParentType> pattern) {
  65. return withChildren(StandardPatterns.<ParentType>collection().last(pattern));
  66. }
  67. public Self withChildren(@NotNull final ElementPattern<Collection<ParentType>> pattern) {
  68. return with(new PatternConditionPlus<T, Collection<ParentType>>("withChildren", pattern) {
  69. @Override
  70. public boolean processValues(T t,
  71. ProcessingContext context,
  72. PairProcessor<Collection<ParentType>, ProcessingContext> processor) {
  73. return processor.process(Arrays.asList(getChildren(t)), context);
  74. }
  75. });
  76. }
  77. public Self isFirstAcceptedChild(@NotNull final ElementPattern<? super ParentType> pattern) {
  78. return with(new PatternCondition<T>("isFirstAcceptedChild") {
  79. public boolean accepts(@NotNull final T t, final ProcessingContext context) {
  80. final ParentType parent = getParent(t);
  81. if (parent != null) {
  82. final ParentType[] children = getChildren(parent);
  83. for (ParentType child : children) {
  84. if (pattern.getCondition().accepts(child, context)) {
  85. return child == t;
  86. }
  87. }
  88. }
  89. return false;
  90. }
  91. });
  92. }
  93. public Self withSuperParent(final int level, @NotNull final Class<? extends ParentType> aClass) {
  94. return withSuperParent(level, StandardPatterns.instanceOf(aClass));
  95. }
  96. public Self withSuperParent(final int level, @NotNull final ElementPattern<? extends ParentType> pattern) {
  97. return with(new PatternConditionPlus<T, ParentType>("withSuperParent", pattern) {
  98. @Override
  99. public boolean processValues(T t,
  100. ProcessingContext context,
  101. PairProcessor<ParentType, ProcessingContext> processor) {
  102. ParentType parent = t;
  103. for (int i = 0; i < level; i++) {
  104. if (parent == null) return false;
  105. parent = getParent(parent);
  106. }
  107. return processor.process(parent, context);
  108. }
  109. });
  110. }
  111. public Self inside(@NotNull final Class<? extends ParentType> pattern) {
  112. return inside(StandardPatterns.instanceOf(pattern));
  113. }
  114. public Self inside(@NotNull final ElementPattern<? extends ParentType> pattern) {
  115. return inside(false, pattern);
  116. }
  117. public Self inside(final boolean strict, @NotNull final ElementPattern<? extends ParentType> pattern) {
  118. return with(new PatternConditionPlus<T, ParentType>("inside", pattern) {
  119. @Override
  120. public boolean processValues(T t,
  121. ProcessingContext context,
  122. PairProcessor<ParentType, ProcessingContext> processor) {
  123. ParentType element = strict ? getParent(t) : t;
  124. while (element != null) {
  125. if (!processor.process(element, context)) return false;
  126. element = getParent(element);
  127. }
  128. return true;
  129. }
  130. });
  131. }
  132. public Self inside(final boolean strict, @NotNull final ElementPattern<? extends ParentType> pattern,
  133. @NotNull final ElementPattern<? extends ParentType> stopAt) {
  134. return with(new PatternCondition<T>("inside") {
  135. @Override
  136. public boolean accepts(@NotNull T t, ProcessingContext context) {
  137. ParentType element = strict ? getParent(t) : t;
  138. while (element != null) {
  139. if (stopAt.getCondition().accepts(element, context)) return false;
  140. if (pattern.getCondition().accepts(element, context)) return true;
  141. element = getParent(element);
  142. }
  143. return false;
  144. }
  145. });
  146. }
  147. /**
  148. * @param strict
  149. * @return Ensures that first elements in hierarchy accepted by patterns appear in specified order
  150. */
  151. public Self insideSequence(final boolean strict, @NotNull final ElementPattern<? extends ParentType>... patterns) {
  152. return with(new PatternCondition<T>("insideSequence") {
  153. public boolean accepts(@NotNull final T t, final ProcessingContext context) {
  154. int i = 0;
  155. ParentType element = strict ? getParent(t) : t;
  156. while (element != null && i < patterns.length) {
  157. for (int j = i; j < patterns.length; j++) {
  158. if (patterns[j].accepts(element, context)) {
  159. if (i != j) return false;
  160. i++;
  161. break;
  162. }
  163. }
  164. element = getParent(element);
  165. }
  166. return true;
  167. }
  168. });
  169. }
  170. public Self afterSibling(final ElementPattern<? extends ParentType> pattern) {
  171. return with(new PatternCondition<T>("afterSibling") {
  172. @Override
  173. public boolean accepts(@NotNull T t, ProcessingContext context) {
  174. final ParentType parent = getParent(t);
  175. if (parent == null) return false;
  176. final ParentType[] children = getChildren(parent);
  177. final int i = Arrays.asList(children).indexOf(t);
  178. if (i <= 0) return false;
  179. return pattern.accepts(children[i - 1], context);
  180. }
  181. });
  182. }
  183. public Self afterSiblingSkipping(@NotNull final ElementPattern skip, final ElementPattern<? extends ParentType> pattern) {
  184. return with(new PatternCondition<T>("afterSiblingSkipping") {
  185. @Override
  186. public boolean accepts(@NotNull T t, ProcessingContext context) {
  187. final ParentType parent = getParent(t);
  188. if (parent == null) return false;
  189. final ParentType[] children = getChildren(parent);
  190. int i = Arrays.asList(children).indexOf(t);
  191. while (--i >= 0) {
  192. if (!skip.accepts(children[i], context)) {
  193. return pattern.accepts(children[i], context);
  194. }
  195. }
  196. return false;
  197. }
  198. });
  199. }
  200. }