/* * Copyright 2013-2015 Grzegorz Ligas <ligasgr@gmail.com> and other contributors * (see the CONTRIBUTORS file). * * 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.xquery.annotator.duplicateFunction; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElement; import org.intellij.xquery.model.XQueryQName; import org.intellij.xquery.psi.XQueryFile; import org.intellij.xquery.psi.XQueryFunctionDecl; import org.intellij.xquery.psi.XQueryFunctionName; import org.intellij.xquery.psi.XQueryModuleDecl; import org.intellij.xquery.psi.XQueryModuleImport; import org.intellij.xquery.psi.XQueryPrefix; import org.intellij.xquery.psi.XQueryURILiteral; import java.util.Collection; import static com.intellij.util.containers.ContainerUtil.filter; import static org.intellij.xquery.model.XQueryQNameBuilder.aXQueryQName; import static org.intellij.xquery.util.StringUtils.removeQuotOrAposIfNeeded; public class Determiner { public static final Condition<XQueryModuleImport> NO_CONDITION = new Condition<XQueryModuleImport>() { @Override public boolean value(XQueryModuleImport xQueryModuleImport) { return true; } }; public boolean hasDuplicateDeclarationInTheSameFile(XQueryFunctionName functionName, XQueryFile file) { boolean result = false; if (functionName.getParent() instanceof XQueryFunctionDecl) { final XQueryFunctionDecl functionDeclaration = (XQueryFunctionDecl) functionName.getParent(); Collection<XQueryFunctionDecl> filteredDeclarations = filter(file.getFunctionDeclarations(), new Condition<XQueryFunctionDecl>() { @Override public boolean value(XQueryFunctionDecl otherFunctionDeclaration) { return functionDeclaration != otherFunctionDeclaration; } }); result = hasDuplicate(functionName, filteredDeclarations); } return result; } public XQueryFile getImportedFileWithDuplicatedDeclaration(XQueryFunctionName functionName, XQueryFile file) { XQueryFile result = null; if (functionName.getParent() instanceof XQueryFunctionDecl) { Collection<XQueryFile> importedFiles = file.getImportedFilesThatExist(NO_CONDITION); result = getImportedFileOrNull(functionName, file, importedFiles); } return result; } private XQueryFile getImportedFileOrNull(XQueryFunctionName functionName, XQueryFile file, Collection<XQueryFile> importedFiles) { for (XQueryFile importedFile : importedFiles) { XQueryPrefix functionNamespaceObject = functionName.getPrefix(); XQueryModuleDecl moduleDeclaration = importedFile.getModuleDeclaration(); XQueryURILiteral uriLiteral = moduleDeclaration != null ? moduleDeclaration.getURILiteral() : null; if (hasDuplicatedNamespaceValue(file, functionNamespaceObject, uriLiteral)) { return getImportedFileOrNull(functionName, importedFile); } } return null; } private boolean hasDuplicatedNamespaceValue(XQueryFile file, XQueryPrefix functionNamespaceObject, XQueryURILiteral uriLiteral) { if (functionNamespaceObject != null && uriLiteral != null) { String functionNamespace = functionNamespaceObject.getText(); String namespaceValue = file.mapFunctionPrefixToNamespace(functionNamespace); String importedFileNamespaceValue = removeQuotOrAposIfNeeded(uriLiteral.getText()); if (importedFileNamespaceValue.equals(namespaceValue)) { return true; } } return false; } private XQueryFile getImportedFileOrNull(XQueryFunctionName functionName, XQueryFile importedFile) { Collection<XQueryFunctionDecl> importedFunctionDeclarations = importedFile.getFunctionDeclarations(); for (XQueryFunctionDecl importedFunctionDeclaration : importedFunctionDeclarations) { if (nameIsTheSame(functionName, importedFunctionDeclaration) && arityIsTheSame(functionName, importedFunctionDeclaration)) { return importedFile; } } return null; } private boolean hasDuplicate(XQueryFunctionName functionName, Collection<XQueryFunctionDecl> functionDeclarations) { for (XQueryFunctionDecl otherFunctionDeclaration : functionDeclarations) { if (nameIsTheSame(functionName, otherFunctionDeclaration) && arityIsTheSame(functionName, otherFunctionDeclaration)) { return true; } } return false; } private boolean nameIsTheSame(XQueryFunctionName functionName, XQueryFunctionDecl otherFunctionDeclaration) { XQueryFunctionName otherFunctionName = otherFunctionDeclaration.getFunctionName(); if (otherFunctionName != null) { XQueryQName<XQueryFunctionName> source = aXQueryQName(functionName).build(); XQueryQName<XQueryFunctionName> checkedQName = aXQueryQName(otherFunctionName).build(); return source.equals(checkedQName); } else { return false; } } private boolean arityIsTheSame(XQueryFunctionName functionName, XQueryFunctionDecl otherFunctionDeclaration) { PsiElement parent = functionName.getParent(); return otherFunctionDeclaration.getArity() == ((XQueryFunctionDecl) parent).getArity(); } }