| /* |
| * 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.refactoring; |
| |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiFile; |
| import com.intellij.psi.PsiNamedElement; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.refactoring.util.CommonRefactoringUtil; |
| import com.intellij.util.containers.MultiMap; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForClause; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; |
| import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; |
| |
| /** |
| * @author ilyas |
| */ |
| public class GroovyValidationUtil { |
| |
| private GroovyValidationUtil() { |
| } |
| |
| public static boolean validateNewParameterName(GrParameter variable, MultiMap<PsiElement,String> conflicts, @NotNull String varName) { |
| GrParameterList list = PsiTreeUtil.getParentOfType(variable, GrParameterList.class); |
| GrParametersOwner owner = PsiTreeUtil.getParentOfType(variable, GrParametersOwner.class); |
| assert owner != null; |
| for (GrParameter parameter : list.getParameters()) { |
| if (parameter.equals(variable)) continue; |
| validateVariableOccurrencesDownImpl(parameter, conflicts, varName); |
| } |
| validateVariableOccurrencesDown(owner, list, conflicts, varName); |
| PsiElement parent = owner.getParent(); |
| validateVariableOccurrencesUp(parent, owner, conflicts, varName, parent instanceof GroovyFile); |
| return conflicts.isEmpty(); |
| } |
| |
| |
| private static void validateVariableOccurrencesUp(PsiElement parent, |
| PsiElement lastParent, |
| MultiMap<PsiElement, String> conflicts, |
| @NotNull String varName, |
| final boolean containerIsFile) { |
| if (!containerIsFile && (parent instanceof PsiFile) || parent == null) return; |
| |
| PsiElement child = parent.getFirstChild(); |
| while (child != null && child != lastParent) { // Upper variable declarations |
| if (child instanceof GrVariableDeclaration) { |
| for (GrVariable variable : ((GrVariableDeclaration)child).getVariables()) { |
| if (varName.equals(variable.getName())) { |
| addConflict(varName, variable, conflicts); |
| } |
| } |
| } |
| child = child.getNextSibling(); |
| } |
| if (parent instanceof GrParametersOwner) { //method or closure parameters |
| GrParametersOwner owner = (GrParametersOwner)parent; |
| for (GrParameter parameter : owner.getParameters()) { |
| if (varName.equals(parameter.getName())) { |
| addConflict(varName, parameter, conflicts); |
| } |
| } |
| } else if (parent instanceof GrForStatement) { // For statement binding |
| GrForStatement statement = (GrForStatement)parent; |
| GrForClause clause = statement.getClause(); |
| if (clause != null) { |
| final GrVariable variable = clause.getDeclaredVariable(); |
| if (variable != null && varName.equals(variable.getName())) { |
| addConflict(varName, variable, conflicts); |
| } |
| } |
| } |
| if (parent instanceof PsiFile) return; |
| validateVariableOccurrencesUp(parent.getParent(), parent, conflicts, varName, false); |
| } |
| |
| |
| private static void validateVariableOccurrencesDown(PsiElement parent, |
| PsiElement startChild, |
| MultiMap<PsiElement, String> conflicts, |
| @NotNull String varName) { |
| PsiElement child = parent.getLastChild(); |
| while (child != null && child != startChild && !(child instanceof GrTypeDefinition)) { |
| validateVariableOccurrencesDownImpl(child, conflicts, varName); |
| child = child.getPrevSibling(); |
| } |
| } |
| |
| private static void validateVariableOccurrencesDownImpl(final PsiElement child, final MultiMap<PsiElement, String> conflicts, final String varName) { |
| if (child instanceof PsiNamedElement) { |
| PsiNamedElement element = (PsiNamedElement)child; |
| if (varName.equals(element.getName())) { |
| addConflict(varName, element, conflicts); |
| } else { |
| for (PsiElement psiElement : child.getChildren()) { |
| if (!(child instanceof GrTypeDefinition)) { |
| validateVariableOccurrencesDownImpl(psiElement, conflicts, varName); |
| } |
| } |
| } |
| } |
| } |
| |
| private static void addConflict(final String varName, final PsiNamedElement element, final MultiMap<PsiElement, String> conflicts) { |
| if (element instanceof GrParameter) { |
| conflicts.putValue(element, GroovyRefactoringBundle.message("variable.conflicts.with.parameter.0", CommonRefactoringUtil.htmlEmphasize(varName))); |
| } else if (element instanceof GrField) { |
| conflicts.putValue(element, GroovyRefactoringBundle.message("variable.conflicts.with.field.0", CommonRefactoringUtil.htmlEmphasize(varName))); |
| } else { |
| conflicts.putValue(element, GroovyRefactoringBundle.message("variable.conflicts.with.variable.0", CommonRefactoringUtil.htmlEmphasize(varName))); |
| } |
| } |
| |
| public static class ParameterNameSuggester { |
| private final String myName; |
| private final GrParameter myParameter; |
| |
| public ParameterNameSuggester(String name, GrParameter parameter) { |
| myName = name; |
| myParameter = parameter; |
| } |
| |
| public String generateName() { |
| String name = myName; |
| int i = 1; |
| MultiMap<PsiElement, String> confl = new MultiMap<PsiElement, String>(); |
| while (!validateNewParameterName(myParameter, confl, name)) { |
| name = myName + i; |
| i++; |
| confl = new MultiMap<PsiElement, String>(); |
| } |
| return name; |
| } |
| } |
| |
| |
| } |