SSR: better canMatch() check to fix PHP structural search inspection
authorBas Leijdekkers <basleijdekkers@gmail.com>
Fri, 4 Nov 2016 19:47:43 +0000 (20:47 +0100)
committerBas Leijdekkers <basleijdekkers@gmail.com>
Fri, 4 Nov 2016 20:16:41 +0000 (21:16 +0100)
platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java
platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/LightTopLevelMatchingHandler.java
platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/MatchingHandler.java
platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SkippingHandler.java
platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SymbolHandler.java
platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/TopLevelMatchingHandler.java

index 4024873eb64616b5c91034a694942f510e707a6b..b4a96d1f30cf5107628a5416d0b1db63de356d82 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.structuralsearch.impl.matcher;
 
 import com.intellij.dupLocator.iterators.ArrayBackedNodeIterator;
@@ -113,7 +128,7 @@ public class MatcherImpl {
           return false;
         }
         final MatchingHandler matchingHandler = pattern.getHandler(patternNode);
-        if (matchingHandler == null || !matchingHandler.canMatch(patternNode, matchedNode)) {
+        if (matchingHandler == null || !matchingHandler.canMatch(patternNode, matchedNode, context)) {
           return false;
         }
         matchedNodes.advance();
@@ -586,7 +601,7 @@ public class MatcherImpl {
       MatchingHandler handler = null;
 
       while (element.getClass() == targetNode.getClass() ||
-             compiledPattern.isTypedVar(targetNode) && compiledPattern.getHandler(targetNode).canMatch(targetNode, element)) {
+             compiledPattern.isTypedVar(targetNode) && compiledPattern.getHandler(targetNode).canMatch(targetNode, element, matchContext)) {
         handler = compiledPattern.getHandler(targetNode);
         handler.setPinnedElement(element);
         elementToStartMatching = element;
index 34941cfa0257b76c058d4b6ed768dd44d0379807..d79805695d4dbbc1d354845bc792cf857f615595 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.structuralsearch.impl.matcher.handlers;
 
 import com.intellij.psi.PsiElement;
@@ -12,13 +27,14 @@ public final class LightTopLevelMatchingHandler extends MatchingHandler implemen
     myDelegate = delegate;
   }
 
+  @Override
   public boolean match(final PsiElement patternNode, final PsiElement matchedNode, final MatchContext matchContext) {
     return myDelegate.match(patternNode, matchedNode, matchContext);
   }
 
   @Override
-  public boolean canMatch(PsiElement patternNode, PsiElement matchedNode) {
-    return myDelegate.canMatch(patternNode, matchedNode);
+  public boolean canMatch(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
+    return myDelegate.canMatch(patternNode, matchedNode, context);
   }
 
   @Override
@@ -26,11 +42,13 @@ public final class LightTopLevelMatchingHandler extends MatchingHandler implemen
     return myDelegate.matchSequentially(nodes, nodes2, context);
   }
 
+  @Override
   public boolean match(final PsiElement patternNode,
                        final PsiElement matchedNode, final int start, final int end, final MatchContext context) {
     return myDelegate.match(patternNode, matchedNode, start, end, context);
   }
 
+  @Override
   public boolean isMatchSequentiallySucceeded(final NodeIterator nodes2) {
     return true;
   }
@@ -40,6 +58,7 @@ public final class LightTopLevelMatchingHandler extends MatchingHandler implemen
     return myDelegate.shouldAdvanceTheMatchFor(patternElement, matchedElement);
   }
 
+  @Override
   public MatchingHandler getDelegate() {
     return myDelegate;
   }
index 2f7b74b4f53c96d80a2f649d47a004b2f0833c98..292d0421e26f2900abefe99b37fdcb7925f21a9e 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.structuralsearch.impl.matcher.handlers;
 
 import com.intellij.dupLocator.iterators.NodeIterator;
@@ -33,7 +48,8 @@ public abstract class MatchingHandler extends MatchPredicate {
    * @param context of the matching
    * @return true if matching was successful and false otherwise
    */
-  public boolean match(PsiElement patternNode,PsiElement matchedNode, int start, int end, MatchContext context) {
+  @Override
+  public boolean match(PsiElement patternNode, PsiElement matchedNode, int start, int end, MatchContext context) {
     return match(patternNode,matchedNode,context);
   }
 
@@ -43,15 +59,16 @@ public abstract class MatchingHandler extends MatchPredicate {
    * @param context of the matching
    * @return true if matching was successful and false otherwise
    */
-  public boolean match(PsiElement patternNode,PsiElement matchedNode, MatchContext context) {
+  @Override
+  public boolean match(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
     if (patternNode == null) {
       return matchedNode == null;
     }
 
-    return canMatch(patternNode, matchedNode);
+    return canMatch(patternNode, matchedNode, context);
   }
 
-  public boolean canMatch(final PsiElement patternNode, final PsiElement matchedNode) {
+  public boolean canMatch(final PsiElement patternNode, final PsiElement matchedNode, MatchContext context) {
     if (filter!=null) {
       return filter.accepts(matchedNode);
     } else {
index 389c4a7916c24144aad0302f599034a8b12249f4..d1a6661f4cf057bd970bbcd8f727f13445c9782c 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.structuralsearch.impl.matcher.handlers;
 
 import com.intellij.dupLocator.equivalence.EquivalenceDescriptor;
@@ -21,6 +36,7 @@ public class SkippingHandler extends MatchingHandler implements DelegatingHandle
     myDelegate = delegate;
   }
 
+  @Override
   public boolean match(PsiElement patternNode, PsiElement matchedNode, final MatchContext matchContext) {
     if (patternNode == null || matchedNode == null || matchedNode.getClass() == patternNode.getClass()) {
       return myDelegate.match(patternNode, matchedNode, matchContext);
@@ -40,8 +56,12 @@ public class SkippingHandler extends MatchingHandler implements DelegatingHandle
   }
 
   @Override
-  public boolean canMatch(PsiElement patternNode, PsiElement matchedNode) {
-    return myDelegate.canMatch(patternNode, matchedNode);
+  public boolean canMatch(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
+    final PsiElement newPatternNode = skipNodeIfNeccessary(patternNode);
+    if (newPatternNode != patternNode) {
+      return context.getPattern().getHandler(newPatternNode).canMatch(newPatternNode, matchedNode, context);
+    }
+    return myDelegate.canMatch(patternNode, matchedNode, context);
   }
 
   @Override
@@ -49,6 +69,7 @@ public class SkippingHandler extends MatchingHandler implements DelegatingHandle
     return myDelegate.matchSequentially(nodes, nodes2, context);
   }
 
+  @Override
   public boolean match(PsiElement patternNode,
                        PsiElement matchedNode,
                        final int start,
@@ -68,6 +89,7 @@ public class SkippingHandler extends MatchingHandler implements DelegatingHandle
     return myDelegate.match(patternNode, matchedNode, start, end, context);
   }
 
+  @Override
   protected boolean isMatchSequentiallySucceeded(final NodeIterator nodes2) {
     return myDelegate.isMatchSequentiallySucceeded(nodes2);
   }
@@ -77,6 +99,7 @@ public class SkippingHandler extends MatchingHandler implements DelegatingHandle
     return true;
   }
 
+  @Override
   public MatchingHandler getDelegate() {
     return myDelegate;
   }
index a366a00d24f281013757adbe70f8f083664dc8bd..04a16d02ca6d452e2c3858565b8bdba389778a47 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.structuralsearch.impl.matcher.handlers;
 
 import com.intellij.psi.PsiElement;
@@ -15,6 +30,6 @@ public class SymbolHandler extends MatchingHandler {
 
   @Override
   public boolean match(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
-    return handler.canMatch(patternNode, matchedNode) && handler.handle(matchedNode, context);
+    return handler.canMatch(patternNode, matchedNode, context) && handler.handle(matchedNode, context);
   }
 }
index ce1c086d1d146bf03a6436a42454fde0d193dc85..5dcc5661820d828e6ff68a652d266c991ae923fc 100644 (file)
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.structuralsearch.impl.matcher.handlers;
 
 import com.intellij.dupLocator.iterators.NodeIterator;
@@ -20,6 +35,7 @@ public final class TopLevelMatchingHandler extends MatchingHandler implements De
     setFilter(_delegate.getFilter());
   }
 
+  @Override
   public boolean match(final PsiElement patternNode, final PsiElement matchedNode, final MatchContext matchContext) {
     final boolean matched = delegate.match(patternNode, matchedNode, matchContext);
 
@@ -56,8 +72,8 @@ public final class TopLevelMatchingHandler extends MatchingHandler implements De
   }
 
   @Override
-  public boolean canMatch(PsiElement patternNode, PsiElement matchedNode) {
-    return delegate.canMatch(patternNode, matchedNode);
+  public boolean canMatch(PsiElement patternNode, PsiElement matchedNode, MatchContext context) {
+    return delegate.canMatch(patternNode, matchedNode, context);
   }
 
   @Override
@@ -65,11 +81,13 @@ public final class TopLevelMatchingHandler extends MatchingHandler implements De
     return delegate.matchSequentially(nodes, nodes2, context);
   }
 
+  @Override
   public boolean match(final PsiElement patternNode,
                        final PsiElement matchedNode, final int start, final int end, final MatchContext context) {
     return match(patternNode, matchedNode, context);
   }
 
+  @Override
   public boolean isMatchSequentiallySucceeded(final NodeIterator nodes2) {
     return true;
   }
@@ -79,6 +97,7 @@ public final class TopLevelMatchingHandler extends MatchingHandler implements De
     return delegate.shouldAdvanceTheMatchFor(patternElement, matchedElement);
   }
 
+  @Override
   public MatchingHandler getDelegate() {
     return delegate;
   }