/******************************************************************************* * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ package com.cisco.yangide.ext.refactoring.actions; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.ltk.core.refactoring.CheckConditionsOperation; import org.eclipse.ltk.core.refactoring.PerformRefactoringOperation; import org.eclipse.ltk.core.refactoring.participants.RenameRefactoring; import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchWindow; import com.cisco.yangide.core.YangTypeUtil; import com.cisco.yangide.core.dom.ASTNamedNode; import com.cisco.yangide.core.dom.ASTNode; import com.cisco.yangide.core.dom.ASTVisitor; import com.cisco.yangide.core.dom.BaseReference; import com.cisco.yangide.core.dom.GroupingDefinition; import com.cisco.yangide.core.dom.IdentitySchemaNode; import com.cisco.yangide.core.dom.Module; import com.cisco.yangide.core.dom.ModuleImport; import com.cisco.yangide.core.dom.SimpleNode; import com.cisco.yangide.core.dom.SubModule; import com.cisco.yangide.core.dom.SubModuleInclude; import com.cisco.yangide.core.dom.TypeDefinition; import com.cisco.yangide.core.dom.TypeReference; import com.cisco.yangide.core.dom.UsesNode; import com.cisco.yangide.ext.refactoring.YangRefactoringPlugin; import com.cisco.yangide.ext.refactoring.rename.RenameGroupingProcessor; import com.cisco.yangide.ext.refactoring.rename.RenameIdentityProcessor; import com.cisco.yangide.ext.refactoring.rename.RenameModuleProcessor; import com.cisco.yangide.ext.refactoring.rename.RenameSubModuleProcessor; import com.cisco.yangide.ext.refactoring.rename.RenameTypeProcessor; import com.cisco.yangide.ext.refactoring.rename.YangRenameProcessor; import com.cisco.yangide.ext.refactoring.ui.RenameRefactoringWizard; /** * Methods to perform Rename refactoring with dialogs or silent. * * @author Konstantin Zaitsev * @date Aug 4, 2014 */ public class RenameSupport { private String newName; private ASTNamedNode node; private IFile file; /** * @param file file where node is declared * @param node node with type or group definition * @param newName new name of node */ public RenameSupport(IFile file, ASTNamedNode node, String newName) { this.file = file; this.node = node; this.newName = newName; } /** * @param shell */ public void openDialog(Shell shell) { openDialog(shell, false); } /** * @param shell * @param showPreview if <code>true</code> will display preview without the first page * @return refactoring status */ public boolean openDialog(Shell shell, boolean showPreview) { YangRenameProcessor<?> processor = getProcessor(shell); if (processor == null) { return false; } RenameRefactoring refactoring = new RenameRefactoring(processor); processor.setNewName(newName); processor.setUpdateReferences(true); processor.setFile(file); RenameRefactoringWizard wizard = null; if (showPreview) { wizard = new RenameRefactoringWizard(refactoring) { @Override protected void addUserInputPages() { } }; wizard.setForcePreviewReview(showPreview); } else { wizard = new RenameRefactoringWizard(refactoring); } RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); try { return op.run(shell, "Rename") == IDialogConstants.OK_ID; } catch (InterruptedException e) { // do nothing } return false; } /** * Performs rename refactoring. * * @param shell * @param window */ public void perform(Shell shell, IWorkbenchWindow window) { YangRenameProcessor<?> processor = getProcessor(shell); if (processor != null) { RenameRefactoring refactoring = new RenameRefactoring(processor); processor.setNewName(newName); processor.setUpdateReferences(true); processor.setFile(file); PerformRefactoringOperation op = new PerformRefactoringOperation(refactoring, CheckConditionsOperation.ALL_CONDITIONS); try { op.run(null); } catch (CoreException e) { YangRefactoringPlugin.log(e); } } } /** * @param shell shell * @return create appropriate refactor processor by node type */ private YangRenameProcessor<?> getProcessor(Shell shell) { YangRenameProcessor<?> processor = null; if (node instanceof GroupingDefinition) { processor = new RenameGroupingProcessor((GroupingDefinition) node); } else if (node instanceof TypeDefinition) { processor = new RenameTypeProcessor((TypeDefinition) node); } else if (node instanceof IdentitySchemaNode) { processor = new RenameIdentityProcessor((IdentitySchemaNode) node); } else if (node instanceof SubModule) { processor = new RenameSubModuleProcessor((SubModule) node); } else if (node instanceof Module) { processor = new RenameModuleProcessor((Module) node); } return processor; } /** * @param node node to inspect * @return <code>true</code> if node available to rename */ public static boolean isDirectRename(ASTNode node) { return node instanceof GroupingDefinition || node instanceof TypeDefinition || node instanceof IdentitySchemaNode || node instanceof Module || node instanceof SubModule; } /** * @param node node to inspect * @return <code>true</code> if node is reference to perform indirect renaming */ public static boolean isIndirectRename(ASTNode node) { return node instanceof UsesNode || (node instanceof TypeReference && !YangTypeUtil.isBuiltInType(((TypeReference) node).getName())) || node instanceof BaseReference || node instanceof ModuleImport || node instanceof SubModuleInclude; } /** * @param module module to find * @param node original node with definition * @return arrays of referenced node with original node */ public static ASTNamedNode[] findLocalReferences(Module module, final ASTNamedNode node) { final List<ASTNamedNode> nodes = new ArrayList<>(); final String name = node.getName(); final SimpleNode<String> modulePrefix = module.getPrefix(); module.accept(new ASTVisitor() { @Override public void preVisit(ASTNode n) { if (n instanceof ASTNamedNode) { ASTNamedNode nn = (ASTNamedNode) n; if ((nn instanceof TypeDefinition || nn instanceof GroupingDefinition || nn instanceof Module || nn instanceof SubModule || nn instanceof IdentitySchemaNode) && nn.getName().equals(name)) { nodes.add(nn); } else if (nn instanceof TypeReference && ((TypeReference) nn).getType().getName().equals(name)) { nodes.add(nn); } else if (nn instanceof UsesNode && ((UsesNode) nn).getGrouping().getName().equals(name)) { // We add the node if the prefix on the UsesNode matches the module prefix, // either implicitly or explicitly. if (((UsesNode) nn).getGrouping().getPrefix() != null && modulePrefix != null && ((UsesNode) nn).getGrouping().getPrefix().equals(modulePrefix.getValue())) { nodes.add(nn); } } else if (nn instanceof BaseReference && ((BaseReference) nn).getType().getName().equals(name)) { nodes.add(nn); } else if (nn instanceof ModuleImport && ((ModuleImport) nn).getName().equals(name)) { nodes.add(nn); } else if (nn instanceof SubModuleInclude && ((SubModuleInclude) nn).getName().equals(name)) { nodes.add(nn); } } } }); return nodes.toArray(new ASTNamedNode[nodes.size()]); } }