mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 09:46:02 +02:00
Refactoring code for potential future use.
This commit is contained in:
parent
0f4f703be2
commit
e1c9238c80
5 changed files with 393 additions and 0 deletions
|
@ -0,0 +1,41 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2012 IBM Corporation 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
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.refactoring.utils;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.corext.refactoring.code.flow.Selection;
|
||||||
|
|
||||||
|
public class CodeAnalyzer extends StatementAnalyzer {
|
||||||
|
|
||||||
|
public CodeAnalyzer(ITranslationUnit cunit, Selection selection, boolean traverseSelectedNode)
|
||||||
|
throws CoreException {
|
||||||
|
super(cunit, selection, traverseSelectedNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void checkSelectedNodes() {
|
||||||
|
super.checkSelectedNodes();
|
||||||
|
RefactoringStatus status= getStatus();
|
||||||
|
if (status.hasFatalError())
|
||||||
|
return;
|
||||||
|
IASTNode node= getFirstSelectedNode();
|
||||||
|
if (node instanceof IASTInitializerList) {
|
||||||
|
status.addFatalError(Messages.CodeAnalyzer_initializer_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,16 @@ public final class Messages extends NLS {
|
||||||
public static String IdentifierHelper_unidentifiedMistake;
|
public static String IdentifierHelper_unidentifiedMistake;
|
||||||
public static String Checks_validate_edit;
|
public static String Checks_validate_edit;
|
||||||
public static String Checks_choose_name;
|
public static String Checks_choose_name;
|
||||||
|
public static String CodeAnalyzer_initializer_list;
|
||||||
|
public static String StatementAnalyzer_doesNotCover;
|
||||||
|
public static String StatementAnalyzer_do_body_expression;
|
||||||
|
public static String StatementAnalyzer_for_initializer_expression;
|
||||||
|
public static String StatementAnalyzer_for_expression_updater;
|
||||||
|
public static String StatementAnalyzer_for_updater_body;
|
||||||
|
public static String StatementAnalyzer_catch_argument;
|
||||||
|
public static String StatementAnalyzer_while_expression_body;
|
||||||
|
public static String StatementAnalyzer_try_statement;
|
||||||
|
public static String StatementAnalyzer_switch_statement;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
NLS.initializeMessages(Messages.class.getName(), Messages.class);
|
NLS.initializeMessages(Messages.class.getName(), Messages.class);
|
||||||
|
|
|
@ -19,3 +19,13 @@ IdentifierHelper_illegalCharacter=Illegal character found in ''{0}''.
|
||||||
IdentifierHelper_unidentifiedMistake=''{0}'' contains an unidentified mistake.
|
IdentifierHelper_unidentifiedMistake=''{0}'' contains an unidentified mistake.
|
||||||
Checks_validate_edit=Team provider refused file modification.
|
Checks_validate_edit=Team provider refused file modification.
|
||||||
Checks_choose_name=Choose a name.
|
Checks_choose_name=Choose a name.
|
||||||
|
CodeAnalyzer_initializer_list=Operation is not applicable to an initializer list.
|
||||||
|
StatementAnalyzer_doesNotCover=The selection does not cover a set of statements or an expression. Extend selection to a valid range using the \'Expand Selection To\' actions from the \'Edit\' menu.
|
||||||
|
StatementAnalyzer_do_body_expression=Operation not applicable to a \'do\' statement's body and expression.
|
||||||
|
StatementAnalyzer_for_initializer_expression=Operation not applicable to a \'for\' statement's initializer and expression part.
|
||||||
|
StatementAnalyzer_for_expression_updater=Operation not applicable to a \'for\' statement's condition and updater part.
|
||||||
|
StatementAnalyzer_for_updater_body=Operation not applicable to a \'for\' statement's updater and body part.
|
||||||
|
StatementAnalyzer_catch_argument=Operation is not applicable to a catch block's argument declaration.
|
||||||
|
StatementAnalyzer_while_expression_body=Operation not applicable to a while statement's expression and body.
|
||||||
|
StatementAnalyzer_try_statement=Selection must either cover a whole try statement or parts of try, catch, or finally block.
|
||||||
|
StatementAnalyzer_switch_statement=Selection must either cover a whole switch statement or parts of a single case block.
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2012 IBM Corporation 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
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.refactoring.utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.Assert;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.Region;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.corext.refactoring.code.flow.Selection;
|
||||||
|
import org.eclipse.cdt.internal.corext.util.ASTNodes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a selection to a set of AST nodes.
|
||||||
|
*/
|
||||||
|
public class SelectionAnalyzer extends ASTGenericVisitor {
|
||||||
|
private Selection fSelection;
|
||||||
|
private final boolean fTraverseSelectedNode;
|
||||||
|
private IASTNode fLastCoveringNode;
|
||||||
|
|
||||||
|
// Selected nodes
|
||||||
|
private List<IASTNode> fSelectedNodes;
|
||||||
|
|
||||||
|
public SelectionAnalyzer(Selection selection, boolean traverseSelectedNode) {
|
||||||
|
super(true);
|
||||||
|
Assert.isNotNull(selection);
|
||||||
|
fSelection= selection;
|
||||||
|
fTraverseSelectedNode= traverseSelectedNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setSelection(Selection selection) {
|
||||||
|
fSelection= selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSelectedNodes() {
|
||||||
|
return fSelectedNodes != null && !fSelectedNodes.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode[] getSelectedNodes() {
|
||||||
|
if (fSelectedNodes == null || fSelectedNodes.isEmpty())
|
||||||
|
return new IASTNode[0];
|
||||||
|
return fSelectedNodes.toArray(new IASTNode[fSelectedNodes.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode getFirstSelectedNode() {
|
||||||
|
if (fSelectedNodes == null || fSelectedNodes.isEmpty())
|
||||||
|
return null;
|
||||||
|
return fSelectedNodes.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode getLastSelectedNode() {
|
||||||
|
if (fSelectedNodes == null || fSelectedNodes.isEmpty())
|
||||||
|
return null;
|
||||||
|
return fSelectedNodes.get(fSelectedNodes.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExpressionSelected() {
|
||||||
|
if (!hasSelectedNodes())
|
||||||
|
return false;
|
||||||
|
return fSelectedNodes.get(0) instanceof IASTExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IRegion getSelectedNodeRange() {
|
||||||
|
if (fSelectedNodes == null || fSelectedNodes.isEmpty())
|
||||||
|
return null;
|
||||||
|
IASTNode firstNode= fSelectedNodes.get(0);
|
||||||
|
int start= firstNode.getFileLocation().getNodeOffset();
|
||||||
|
IASTNode lastNode= fSelectedNodes.get(fSelectedNodes.size() - 1);
|
||||||
|
return new Region(start, ASTNodes.endOffset(lastNode) - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTNode getLastCoveringNode() {
|
||||||
|
return fLastCoveringNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Selection getSelection() {
|
||||||
|
return fSelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- node management ---------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int genericVisit(IASTNode node) {
|
||||||
|
// The selection lies behind the node.
|
||||||
|
if (fSelection.liesOutside(node)) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
} else if (fSelection.covers(node)) {
|
||||||
|
if (isFirstNode()) {
|
||||||
|
handleFirstSelectedNode(node);
|
||||||
|
} else {
|
||||||
|
handleNextSelectedNode(node);
|
||||||
|
}
|
||||||
|
return fTraverseSelectedNode ? PROCESS_CONTINUE : PROCESS_SKIP;
|
||||||
|
} else if (fSelection.coveredBy(node)) {
|
||||||
|
fLastCoveringNode= node;
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
} else if (fSelection.endsIn(node)) {
|
||||||
|
return handleSelectionEndsIn(node) ? PROCESS_CONTINUE : PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
// There is a possibility that the user has selected trailing semicolons that don't belong
|
||||||
|
// to the statement. So dive into it to check if sub nodes are fully covered.
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset() {
|
||||||
|
fSelectedNodes= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleFirstSelectedNode(IASTNode node) {
|
||||||
|
fSelectedNodes= new ArrayList<IASTNode>(5);
|
||||||
|
fSelectedNodes.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleNextSelectedNode(IASTNode node) {
|
||||||
|
if (getFirstSelectedNode().getParent() == node.getParent()) {
|
||||||
|
fSelectedNodes.add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean handleSelectionEndsIn(IASTNode node) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<IASTNode> internalGetSelectedNodes() {
|
||||||
|
return fSelectedNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isFirstNode() {
|
||||||
|
return fSelectedNodes == null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2012 IBM Corporation 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
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* IBM Corporation - initial API and implementation
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.refactoring.utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.Assert;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
|
||||||
|
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDoStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.corext.refactoring.code.flow.Selection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyzer to check if a selection covers a valid set of statements of an abstract syntax
|
||||||
|
* tree. The selection is valid iff
|
||||||
|
* <ul>
|
||||||
|
* <li>it does not start or end in the middle of a comment.</li>
|
||||||
|
* <li>no extract characters except the empty statement ";" is included in the selection.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class StatementAnalyzer extends SelectionAnalyzer {
|
||||||
|
protected ITranslationUnit fTranslationUnit;
|
||||||
|
private final RefactoringStatus fStatus;
|
||||||
|
|
||||||
|
public StatementAnalyzer(ITranslationUnit tu, Selection selection, boolean traverseSelectedNode)
|
||||||
|
throws CoreException {
|
||||||
|
super(selection, traverseSelectedNode);
|
||||||
|
Assert.isNotNull(tu);
|
||||||
|
this.fTranslationUnit= tu;
|
||||||
|
this.fStatus= new RefactoringStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkSelectedNodes() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public RefactoringStatus getStatus() {
|
||||||
|
return fStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ITranslationUnit getTranslationUnit() {
|
||||||
|
return fTranslationUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int leave(IASTTranslationUnit node) {
|
||||||
|
checkSelectedNodes();
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int leave(IASTStatement node) {
|
||||||
|
if (node instanceof IASTDoStatement) {
|
||||||
|
leave((IASTDoStatement) node);
|
||||||
|
} else if (node instanceof IASTForStatement) {
|
||||||
|
leave((IASTForStatement) node);
|
||||||
|
} else if (node instanceof IASTSwitchStatement) {
|
||||||
|
leave((IASTSwitchStatement) node);
|
||||||
|
} else if (node instanceof IASTWhileStatement) {
|
||||||
|
leave((IASTWhileStatement) node);
|
||||||
|
} else if (node instanceof ICPPASTTryBlockStatement) {
|
||||||
|
leave((ICPPASTTryBlockStatement) node);
|
||||||
|
}
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leave(IASTDoStatement node) {
|
||||||
|
IASTNode[] selectedNodes= getSelectedNodes();
|
||||||
|
if (doAfterValidation(node, selectedNodes)) {
|
||||||
|
if (contains(selectedNodes, node.getBody()) && contains(selectedNodes, node.getCondition())) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_do_body_expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leave(IASTForStatement node) {
|
||||||
|
IASTNode[] selectedNodes= getSelectedNodes();
|
||||||
|
if (doAfterValidation(node, selectedNodes)) {
|
||||||
|
boolean hasConditionPart= contains(selectedNodes, node.getConditionExpression());
|
||||||
|
boolean hasIterationPart= contains(selectedNodes, node.getIterationExpression());
|
||||||
|
if (contains(selectedNodes, node.getInitializerStatement()) && hasConditionPart) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_for_initializer_expression);
|
||||||
|
} else if (hasConditionPart && hasIterationPart) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_for_expression_updater);
|
||||||
|
} else if (hasIterationPart && contains(selectedNodes, node.getBody())) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_for_updater_body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leave(ICPPASTTryBlockStatement node) {
|
||||||
|
IASTNode firstSelectedNode= getFirstSelectedNode();
|
||||||
|
if (getSelection().getEndVisitSelectionMode(node) == Selection.AFTER) {
|
||||||
|
if (firstSelectedNode == node.getTryBody()) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_try_statement);
|
||||||
|
} else {
|
||||||
|
ICPPASTCatchHandler[] catchHandlers = node.getCatchHandlers();
|
||||||
|
for (ICPPASTCatchHandler catchHandler : catchHandlers) {
|
||||||
|
if (catchHandler == firstSelectedNode || catchHandler.getCatchBody() == firstSelectedNode) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_try_statement);
|
||||||
|
} else if (catchHandler.getDeclaration() == firstSelectedNode) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_catch_argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leave(IASTSwitchStatement node) {
|
||||||
|
IASTNode[] selectedNodes= getSelectedNodes();
|
||||||
|
IASTStatement body = node.getBody();
|
||||||
|
IASTNode parent = body instanceof IASTCompoundStatement ? body : node;
|
||||||
|
if (doAfterValidation(parent, selectedNodes)) {
|
||||||
|
for (IASTNode n : selectedNodes) {
|
||||||
|
if (n.getParent() == parent &&
|
||||||
|
(n instanceof IASTCaseStatement || n instanceof IASTDefaultStatement)) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_switch_statement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leave(IASTWhileStatement node) {
|
||||||
|
IASTNode[] selectedNodes= getSelectedNodes();
|
||||||
|
if (doAfterValidation(node, selectedNodes)) {
|
||||||
|
if (contains(selectedNodes, node.getCondition()) && contains(selectedNodes, node.getBody())) {
|
||||||
|
invalidSelection(Messages.StatementAnalyzer_while_expression_body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doAfterValidation(IASTNode node, IASTNode[] selectedNodes) {
|
||||||
|
return selectedNodes.length > 0 && node == selectedNodes[0].getParent() && getSelection().getEndVisitSelectionMode(node) == Selection.AFTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void invalidSelection(String message) {
|
||||||
|
fStatus.addFatalError(message);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void invalidSelection(String message, RefactoringStatusContext context) {
|
||||||
|
fStatus.addFatalError(message, context);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean contains(IASTNode[] nodes, IASTNode node) {
|
||||||
|
for (int i = 0; i < nodes.length; i++) {
|
||||||
|
if (nodes[i] == node)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean contains(IASTNode[] nodes, List<IASTExpression> list) {
|
||||||
|
for (int i = 0; i < nodes.length; i++) {
|
||||||
|
if (list.contains(nodes[i]))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue