| /* |
| * Copyright 2005 Sascha Weinreuter |
| * |
| * 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.intellij.lang.xpath.validation.inspections; |
| |
| import com.intellij.codeInspection.InspectionManager; |
| import com.intellij.codeInspection.LocalQuickFix; |
| import com.intellij.codeInspection.ProblemHighlightType; |
| import com.intellij.lang.Language; |
| import org.intellij.lang.xpath.XPathFileType; |
| import org.intellij.lang.xpath.XPathTokenTypes; |
| import org.intellij.lang.xpath.psi.*; |
| import org.intellij.lang.xpath.validation.ExpectedTypeUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| |
| public class IndexZeroPredicate extends XPathInspection { |
| protected Visitor createVisitor(InspectionManager manager, boolean isOnTheFly) { |
| return new MyVisitor(manager, isOnTheFly); |
| } |
| |
| @NotNull |
| public String getDisplayName() { |
| return "Use of index 0 in XPath predicates"; |
| } |
| |
| @NotNull |
| @NonNls |
| public String getShortName() { |
| return "IndexZeroUsage"; |
| } |
| |
| public boolean isEnabledByDefault() { |
| return true; |
| } |
| |
| protected boolean acceptsLanguage(Language language) { |
| return language == XPathFileType.XPATH.getLanguage() || language == XPathFileType.XPATH2.getLanguage(); |
| } |
| |
| final static class MyVisitor extends Visitor { |
| MyVisitor(InspectionManager manager, boolean isOnTheFly) { |
| super(manager, isOnTheFly); |
| } |
| |
| protected void checkPredicate(XPathPredicate predicate) { |
| final XPathExpression expr = predicate.getPredicateExpression(); |
| if (expr != null) { |
| if (expr.getType() == XPathType.NUMBER) { |
| if (isZero(expr)) { |
| addProblem(myManager.createProblemDescriptor(expr, |
| "Use of 0 as predicate index", (LocalQuickFix)null, |
| ProblemHighlightType.GENERIC_ERROR_OR_WARNING, myOnTheFly)); |
| } |
| } else if (expr instanceof XPathBinaryExpression && expr.getType() == XPathType.BOOLEAN) { |
| final XPathBinaryExpression expression = (XPathBinaryExpression)expr; |
| if (!XPathTokenTypes.BOOLEAN_OPERATIONS.contains(expression.getOperator())) { |
| return; |
| } |
| |
| final XPathExpression lOp = expression.getLOperand(); |
| final XPathExpression rOp = expression.getROperand(); |
| |
| if (isZero(lOp)) { |
| assert lOp != null; |
| |
| if (isPosition(rOp)) { |
| addProblem(myManager.createProblemDescriptor(expr, |
| "Comparing position() to 0", (LocalQuickFix)null, |
| ProblemHighlightType.GENERIC_ERROR_OR_WARNING, myOnTheFly)); |
| } |
| } else if (isZero(rOp)) { |
| assert rOp != null; |
| |
| if (isPosition(lOp)) { |
| addProblem(myManager.createProblemDescriptor(expr, |
| "Comparing position() to 0", (LocalQuickFix)null, |
| ProblemHighlightType.GENERIC_ERROR_OR_WARNING, myOnTheFly)); |
| } |
| } |
| } |
| } |
| } |
| |
| private static boolean isPosition(XPathExpression expression) { |
| expression = ExpectedTypeUtil.unparenthesize(expression); |
| |
| if (!(expression instanceof XPathFunctionCall)) { |
| return false; |
| } |
| |
| final XPathFunctionCall call = (XPathFunctionCall)expression; |
| final PrefixedName qName = call.getQName(); |
| if (qName.getPrefix() != null) return false; |
| return "position".equals(qName.getLocalName()); |
| } |
| |
| private static boolean isZero(XPathExpression op) { |
| op = ExpectedTypeUtil.unparenthesize(op); |
| |
| // TODO: compute constant expression |
| return op != null && "0".equals(op.getText()); |
| } |
| } |
| } |