1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 22:22:11 +02:00

Remove Function Bodies and Remove Unused Declarations refactorings.

Change-Id: I99cfe7e561ab1615c7d4ee8c126e07acbc672196
This commit is contained in:
Sergey Prigogin 2016-08-08 12:01:52 -07:00
parent 3d584f5deb
commit 739281bec7
18 changed files with 1153 additions and 14 deletions

View file

@ -2,13 +2,15 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: org.eclipse.cdt.ui.tests
Bundle-SymbolicName: org.eclipse.cdt.ui.tests; singleton:=true
Bundle-Version: 5.4.0.qualifier
Bundle-Version: 5.5.0.qualifier
Bundle-Activator: org.eclipse.cdt.ui.testplugin.CTestPlugin
Bundle-Localization: plugin
Export-Package: org.eclipse.cdt.ui.testplugin,
org.eclipse.cdt.ui.testplugin.util,
org.eclipse.cdt.ui.tests,
org.eclipse.cdt.ui.tests.DOMAST,
org.eclipse.cdt.ui.tests.chelp,
org.eclipse.cdt.ui.tests.reducer,
org.eclipse.cdt.ui.tests.refactoring,
org.eclipse.cdt.ui.tests.refactoring.rename,
org.eclipse.cdt.ui.tests.text,
@ -34,7 +36,8 @@ Require-Bundle: org.eclipse.jface.text,
org.eclipse.core.expressions,
com.ibm.icu,
org.eclipse.ltk.core.refactoring;bundle-version="3.4.0",
org.eclipse.core.filesystem;bundle-version="1.2.0"
org.eclipse.core.filesystem;bundle-version="1.2.0",
org.eclipse.ltk.ui.refactoring
Bundle-ActivationPolicy: lazy
Bundle-Vendor: Eclipse CDT
Bundle-RequiredExecutionEnvironment: JavaSE-1.8

View file

@ -19,5 +19,6 @@ bin.includes = plugin.xml,\
src/,\
ui/,\
META-INF/,\
.options
.options,\
plugin.properties
src.includes = about.html

View file

@ -0,0 +1,16 @@
###############################################################################
# Copyright (c) 2016 Google, 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
#
# Contributors:
# Sergey Prigogin (Google) - initial implementation
###############################################################################
category.CodeReduction=C++ Code Reduction
command.RemoveFunctionBodies.name=Remove Function Bodies
command.RemoveFunctionBodies.label=Remove &Function Bodies
command.RemoveUnusedDeclarations.name=Remove Unused Declarations
command.RemoveUnusedDeclarations.label=Remove &Unused Declarations
menu.ReduceCode.label=Reduce Code

View file

@ -238,4 +238,49 @@
</filesystem>
</extension>
<extension
point="org.eclipse.ui.commands">
<category
id="org.eclipse.ui.tests.category.codeReduction"
name="%category.CodeReduction"/>
<command
name="%command.RemoveFunctionBodies.name"
categoryId="org.eclipse.ui.tests.category.codeReduction"
id="org.eclipse.cdt.ui.tests.removeFunctionBodies"/>
<command
name="%command.RemoveUnusedDeclarations.name"
categoryId="org.eclipse.ui.tests.category.codeReduction"
id="org.eclipse.cdt.ui.tests.removeUnusedDeclarations"/>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="org.eclipse.cdt.ui.tests.reducer.RemoveFunctionBodiesHandler"
commandId="org.eclipse.cdt.ui.tests.removeFunctionBodies"/>
<handler
class="org.eclipse.cdt.ui.tests.reducer.RemoveUnusedDeclarationsHandler"
commandId="org.eclipse.cdt.ui.tests.removeUnusedDeclarations"/>
</extension>
<extension point="org.eclipse.ui.menus">
<menuContribution
locationURI="popup:#CEditorContext?after=org.eclipse.cdt.ui.source.menu">
<menu
id="org.eclipse.cdt.ui.tests.reduceCode"
label="%menu.ReduceCode.label">
<command
commandId="org.eclipse.cdt.ui.tests.removeFunctionBodies"
label="%command.RemoveFunctionBodies.label"
style="push">
</command>
<command
commandId="org.eclipse.cdt.ui.tests.removeUnusedDeclarations"
label="%command.RemoveUnusedDeclarations.label"
style="push">
</command>
</menu>
</menuContribution>
</extension>
</plugin>

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>5.4.0-SNAPSHOT</version>
<version>5.5.0-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.ui.tests</artifactId>
<packaging>eclipse-test-plugin</packaging>

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.osgi.util.NLS;
final class Messages extends NLS {
public static String RemoveFunctionBodiesRefactoring_RemoveFunctionBodies;
public static String RemoveUnusedDeclarationsRefactoring_RemoveUnusedDeclarations;
static {
NLS.initializeMessages(Messages.class.getName(), Messages.class);
}
// Do not instantiate.
private Messages() {
}
}

View file

@ -0,0 +1,12 @@
###############################################################################
# Copyright (c) 2016 Google, 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
#
# Contributors:
# Sergey Prigogin (Google) - initial implementation
###############################################################################
RemoveFunctionBodiesRefactoring_RemoveFunctionBodies=Remove Function Bodies
RemoveUnusedDeclarationsRefactoring_RemoveUnusedDeclarations=Remove Unused Declarations

View file

@ -0,0 +1,30 @@
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
class ProblemFinder extends ASTVisitor {
boolean foundProblem;
public ProblemFinder() {
shouldVisitNames = true;
shouldVisitImplicitNames = true;
}
public boolean containsProblemBinding(IASTNode node) {
foundProblem = false;
node.accept(this);
return foundProblem;
}
@Override
public int visit(IASTName name) {
if (name.resolveBinding() instanceof IProblemBinding) {
foundProblem = true;
return PROCESS_ABORT;
}
return PROCESS_CONTINUE;
}
}

View file

@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.ICEditor;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner;
public class RemoveFunctionBodiesHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ISelection selection = HandlerUtil.getCurrentSelection(event);
if (selection instanceof ITextSelection) {
IWorkbenchPart part = HandlerUtil.getActivePart(event);
if (part instanceof ICEditor) {
ICEditor editor = (ICEditor) part;
IWorkingCopy wc = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
if (wc != null && wc.getResource() != null) {
RefactoringRunner runner = new RemoveFunctionBodiesRefactoringRunner(wc, selection,
editor.getEditorSite(), wc.getCProject());
runner.run();
}
}
}
return null;
}
}

View file

@ -0,0 +1,214 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.INodeFactory;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.ui.refactoring.CTextFileChange;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.rewrite.util.ASTNodes;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
import org.eclipse.cdt.internal.ui.refactoring.changes.CCompositeChange;
public class RemoveFunctionBodiesRefactoring extends CRefactoring {
private INodeFactory nodeFactory;
private final DefaultCodeFormatterOptions formattingOptions;
private IIndex index;
private IASTTranslationUnit ast;
public RemoveFunctionBodiesRefactoring(ICElement element, ISelection selection, ICProject project) {
super(element, selection, project);
name = Messages.RemoveFunctionBodiesRefactoring_RemoveFunctionBodies;
formattingOptions = new DefaultCodeFormatterOptions(project.getOptions(true));
}
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
throws CoreException, OperationCanceledException {
SubMonitor progress = SubMonitor.convert(pm, 10);
RefactoringStatus status = super.checkInitialConditions(progress.newChild(8));
if (status.hasError()) {
return status;
}
ast = getAST(tu, progress.newChild(1));
index = getIndex();
nodeFactory = ast.getASTNodeFactory();
if (isProgressMonitorCanceled(progress, initStatus))
return initStatus;
return initStatus;
}
private ICPPASTFunctionDeclarator getDeclaration(IASTNode node) {
while (node != null && !(node instanceof IASTFunctionDefinition)) {
node = node.getParent();
}
if (node != null) {
IASTFunctionDeclarator declarator = ((IASTFunctionDefinition) node).getDeclarator();
if (declarator instanceof ICPPASTFunctionDeclarator) {
return (ICPPASTFunctionDeclarator) declarator;
}
}
return null;
}
@Override
public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext checkContext) {
return new RefactoringStatus();
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
// This method bypasses the standard refactoring framework involving ModificationCollector and ASTRewrite since
// it is too slow for the gigantic changes this refactoring has to deal with.
FunctionDefinitionCollector finder = new FunctionDefinitionCollector();
ast.accept(finder);
String code = ast.getRawSignature();
CTextFileChange fileChange = new CTextFileChange(tu.getElementName(), tu);
fileChange.setEdit(new MultiTextEdit());
for (IASTFunctionDefinition definition : finder.functionDefinitions) {
IASTStatement body = definition.getBody();
IASTName name = definition.getDeclarator().getName();
IBinding binding = name.resolveBinding();
if (binding instanceof ICPPInternalBinding) {
IASTNode[] declarations = ((ICPPInternalBinding) binding).getDeclarations();
if (declarations != null && declarations.length != 0
&& ((ASTNode) declarations[0]).getOffset() < ((ASTNode) definition).getOffset()) {
IASTNode node = definition;
IASTNode parent;
while ((parent = node.getParent()) instanceof ICPPASTTemplateDeclaration) {
node = parent;
}
int offset = ASTNodes.offset(node);
int endOffset = ASTNodes.endOffset(node);
offset = skipWhitespaceBefore(offset, code);
// Remove the whole definition since the function is declared already.
fileChange.addEdit(new DeleteEdit(offset, endOffset - offset));
continue;
}
}
int offset = ASTNodes.offset(body);
int endOffset = ASTNodes.endOffset(body);
if (definition instanceof ICPPASTFunctionDefinition) {
ICPPASTConstructorChainInitializer[] initializers =
((ICPPASTFunctionDefinition) definition).getMemberInitializers();
if (initializers.length != 0) {
offset = ASTNodes.offset(initializers[0]);
offset = skipWhitespaceBefore(offset, code);
if (offset > 0 && code.charAt(offset - 1) == ':')
offset--;
}
}
offset = skipWhitespaceBefore(offset, code);
fileChange.addEdit(new ReplaceEdit(offset, endOffset - offset, ";"));
}
CCompositeChange change = new CCompositeChange(""); //$NON-NLS-1$
change.markAsSynthetic();
change.add(fileChange);
change.setDescription(new RefactoringChangeDescriptor(getRefactoringDescriptor()));
return change;
}
private static int skipWhitespaceBefore(int offset, String text) {
while (--offset >= 0) {
char c = text.charAt(offset);
if (!Character.isWhitespace(c))
break;
}
return offset + 1;
}
@Override
protected void collectModifications(IProgressMonitor pm, ModificationCollector collector)
throws CoreException, OperationCanceledException {
// This method is no-op for this refactoring. The change is created in the createChange method.
}
/**
* Finds function definitions that have bodies, are not constexpr, and don't contain problem bindings.
*/
private class FunctionDefinitionCollector extends ASTVisitor {
final List<IASTFunctionDefinition> functionDefinitions = new ArrayList<>();
final ProblemFinder problemFinder = new ProblemFinder();
FunctionDefinitionCollector() {
shouldVisitDeclarations = true;
}
@Override
public int visit(IASTDeclaration declaration) {
if (!declaration.isPartOfTranslationUnitFile())
return PROCESS_SKIP;
if (!(declaration instanceof IASTFunctionDefinition))
return PROCESS_CONTINUE;
IASTFunctionDefinition definition = (IASTFunctionDefinition) declaration;
if (definition.getBody() == null)
return PROCESS_SKIP;
IASTDeclSpecifier declSpec = definition.getDeclSpecifier();
if (declSpec instanceof ICPPASTDeclSpecifier && ((ICPPASTDeclSpecifier) declSpec).isConstexpr())
return PROCESS_SKIP;
if (problemFinder.containsProblemBinding(declaration))
return PROCESS_SKIP;
functionDefinitions.add(definition);
return PROCESS_SKIP;
}
}
@Override
protected RefactoringDescriptor getRefactoringDescriptor() {
return null;
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper;
public class RemoveFunctionBodiesRefactoringRunner extends RefactoringRunner {
public RemoveFunctionBodiesRefactoringRunner(ICElement element, ISelection selection,
IShellProvider shellProvider, ICProject cProject) {
super(element, selection, shellProvider, cProject);
}
@Override
public void run() {
RemoveFunctionBodiesRefactoring refactoring =
new RemoveFunctionBodiesRefactoring(element, selection, project);
RemoveFunctionBodiesWizard wizard = new RemoveFunctionBodiesWizard(refactoring);
run(wizard, refactoring, RefactoringSaveHelper.SAVE_NOTHING);
}
}

View file

@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
import org.eclipse.cdt.ui.CUIPlugin;
public class RemoveFunctionBodiesWizard extends RefactoringWizard {
public RemoveFunctionBodiesWizard(RemoveFunctionBodiesRefactoring refactoring) {
super(refactoring, DIALOG_BASED_USER_INTERFACE | PREVIEW_EXPAND_FIRST_NODE);
setDefaultPageTitle(Messages.RemoveFunctionBodiesRefactoring_RemoveFunctionBodies);
setDialogSettings(CUIPlugin.getDefault().getDialogSettings());
}
@Override
protected void addUserInputPages() {
}
}

View file

@ -0,0 +1,46 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.ICEditor;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner;
public class RemoveUnusedDeclarationsHandler extends AbstractHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
ISelection selection = HandlerUtil.getCurrentSelection(event);
if (selection instanceof ITextSelection) {
IWorkbenchPart part = HandlerUtil.getActivePart(event);
if (part instanceof ICEditor) {
ICEditor editor = (ICEditor) part;
IWorkingCopy wc = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(editor.getEditorInput());
if (wc != null && wc.getResource() != null) {
RefactoringRunner runner = new RemoveUnusedDeclarationsRefactoringRunner(wc, selection,
editor.getEditorSite(), wc.getCProject());
runner.run();
}
}
}
return null;
}
}

View file

@ -0,0 +1,72 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.cdt.internal.ui.CPluginImages;
import org.eclipse.cdt.internal.ui.dialogs.TextFieldNavigationHandler;
import org.eclipse.cdt.internal.ui.util.RowLayouter;
public class RemoveUnusedDeclarationsInputPage extends UserInputWizardPage {
public static final String PAGE_NAME = "RemoveUnusedDeclarationsInputPage"; //$NON-NLS-1$
private RemoveFunctionBodiesRefactoring refactoring;
private Text textField;
private IDialogSettings settings;
public RemoveUnusedDeclarationsInputPage() {
super(PAGE_NAME);
setImageDescriptor(CPluginImages.DESC_WIZBAN_REFACTOR_TU);
}
@Override
public void createControl(Composite parent) {
refactoring = (RemoveFunctionBodiesRefactoring) getRefactoring();
Composite result = new Composite(parent, SWT.NONE);
setControl(result);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
result.setLayout(layout);
RowLayouter layouter = new RowLayouter(2);
GridData gd = null;
initializeDialogUnits(result);
Composite group = new Composite(result, SWT.NONE);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
layout = new GridLayout();
layout.numColumns = 4;
layout.marginWidth = 0;
group.setLayout(layout);
}
private Text createTextInputField(Composite parent, int style) {
Text result = new Text(parent, style);
result.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
// textModified(result.getText());
}
});
TextFieldNavigationHandler.install(result);
return result;
}
}

View file

@ -0,0 +1,499 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import static org.eclipse.cdt.internal.core.dom.parser.ASTQueries.findInnermostDeclarator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationListOwner;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.INodeFactory;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.ui.refactoring.CTextFileChange;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.rewrite.util.ASTNodes;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
import org.eclipse.cdt.internal.ui.refactoring.changes.CCompositeChange;
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
public class RemoveUnusedDeclarationsRefactoring extends CRefactoring {
private static final IASTName UNUSED_NAME = new CPPASTName(null);
private static final ProblemFinder problemFinder = new ProblemFinder();
private INodeFactory nodeFactory;
private final DefaultCodeFormatterOptions formattingOptions;
private IIndex index;
private IASTTranslationUnit ast;
private IRegion region;
public RemoveUnusedDeclarationsRefactoring(ICElement element, ISelection selection, ICProject project) {
super(element, selection, project);
name = Messages.RemoveUnusedDeclarationsRefactoring_RemoveUnusedDeclarations;
formattingOptions = new DefaultCodeFormatterOptions(project.getOptions(true));
}
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
throws CoreException, OperationCanceledException {
SubMonitor progress = SubMonitor.convert(pm, 10);
RefactoringStatus status = super.checkInitialConditions(progress.newChild(8));
if (status.hasError()) {
return status;
}
ast = getAST(tu, progress.newChild(1));
index = getIndex();
nodeFactory = ast.getASTNodeFactory();
region = selectedRegion.getLength() == 0 ?
new Region(0, ast.getFileLocation().getNodeLength()) : selectedRegion;
if (isProgressMonitorCanceled(progress, initStatus))
return initStatus;
return initStatus;
}
private ICPPASTFunctionDeclarator getDeclaration(IASTNode node) {
while (node != null && !(node instanceof IASTFunctionDefinition)) {
node = node.getParent();
}
if (node != null) {
IASTFunctionDeclarator declarator = ((IASTFunctionDefinition) node).getDeclarator();
if (declarator instanceof ICPPASTFunctionDeclarator) {
return (ICPPASTFunctionDeclarator) declarator;
}
}
return null;
}
@Override
public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext checkContext) {
return new RefactoringStatus();
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
// This method bypasses the standard refactoring framework involving ModificationCollector and ASTRewrite since
// it is too slow for the gigantic changes this refactoring has to deal with.
NavigableSet<IASTName> names = NameCollector.getContainedNames(ast);
SortedNodeSet<IASTNode> nodesToDelete = new SortedNodeSet<>();
IASTPreprocessorMacroExpansion[] macroExpansions = ast.getMacroExpansions();
for (IASTPreprocessorMacroExpansion macroExpansion : macroExpansions) {
IASTName name = macroExpansion.getMacroReference();
if (SelectionHelper.isNodeInsideRegion(name, region)
&& macroExpansion.getMacroDefinition().getExpansion().isEmpty()) {
nodesToDelete.add(macroExpansion);
}
}
CandidateDeclarationFinder finder = new CandidateDeclarationFinder();
ast.accept(finder);
List<IASTDeclaration> declarations = finder.declarations;
for (int i = declarations.size(); --i >= 0;) {
IASTDeclaration declaration = declarations.get(i);
if (SelectionHelper.isNodeInsideRegion(declaration, region)
&& !problemFinder.containsProblemBinding(declaration)
&& !isPossiblyUsed(declaration, names, nodesToDelete)) {
nodesToDelete.add(declaration);
removeContainedNames(declaration, names);
}
}
String code = ast.getRawSignature();
CTextFileChange fileChange = new CTextFileChange(tu.getElementName(), tu);
fileChange.setEdit(new MultiTextEdit());
int maxOffset = 0;
TextEdit lastEdit = null;
IASTNode lastNode = null;
for (IASTNode node : nodesToDelete) {
int offset = ASTNodes.offset(node);
int endOffset = ASTNodes.endOffset(node);
offset = skipWhitespaceBefore(offset, code);
if (offset < region.getOffset())
offset = region.getOffset();
// Do not attempt to delete nodes inside a deleted region.
if (endOffset > maxOffset) {
DeleteEdit edit = new DeleteEdit(offset, endOffset - offset);
fileChange.addEdit(edit);
if (maxOffset < endOffset)
maxOffset = endOffset;
lastEdit = edit;
lastNode = node;
}
}
CCompositeChange change = new CCompositeChange(""); //$NON-NLS-1$
change.markAsSynthetic();
change.add(fileChange);
change.setDescription(new RefactoringChangeDescriptor(getRefactoringDescriptor()));
return change;
}
private boolean containsAncestor(Collection<IASTNode> nodes, IASTNode node) {
while ((node = node.getParent()) != null) {
if (nodes.contains(node))
return true;
}
return false;
}
private IASTNode getTopMostContainer(IASTNode node) {
while (node != null) {
IASTNode prevNode = node;
node = node.getParent();
if (node instanceof IASTTranslationUnit)
return prevNode;
}
return null;
}
private boolean isPossiblyUsed(IASTDeclaration declaration, NavigableSet<IASTName> names,
SortedNodeSet<IASTNode> nodesToDelete) {
if (declaration instanceof ICPPASTNamespaceDefinition) {
// An empty namespace definition can be removed.
IASTDeclaration[] children = ((ICPPASTNamespaceDefinition) declaration).getDeclarations(false);
for (IASTDeclaration child : children) {
if (!nodesToDelete.contains(child))
return true;
}
return false;
} else if (declaration instanceof ICPPASTLinkageSpecification) {
// An empty linkage specification can be removed.
IASTDeclaration[] children = ((ICPPASTLinkageSpecification) declaration).getDeclarations(false);
for (IASTDeclaration child : children) {
if (!nodesToDelete.contains(child))
return true;
}
return false;
} else if (declaration instanceof ICPPASTVisibilityLabel) {
// A visibility label not followed by a member declaration can be removed.
IASTNode parent = declaration.getParent();
IASTDeclaration[] siblings = ((ICPPASTCompositeTypeSpecifier) parent).getDeclarations(false);
boolean after = false;
for (IASTDeclaration sibling : siblings) {
if (after) {
if (sibling instanceof ICPPASTVisibilityLabel)
break;
if (!nodesToDelete.contains(sibling))
return true;
} else if (sibling == declaration) {
after = true;
}
}
return false;
}
Collection<IASTName> declaredNames = getDeclaredNames(declaration);
if (declaredNames == null)
return true;
for (IASTName declName : declaredNames) {
char[] declNameChars = declName.getSimpleID();
if (declNameChars.length != 0 && declNameChars[0] == '~')
declNameChars = Arrays.copyOfRange(declNameChars, 1, declNameChars.length);
IASTNode startPoint = declName;
int startOffset = ASTNodes.endOffset(declaration);
if (declaration.getPropertyInParent() == IASTCompositeTypeSpecifier.MEMBER_DECLARATION) {
// Member declarations can be referenced by other members declared before them.
startPoint = declaration.getParent();
startOffset = ASTNodes.offset(startPoint);
} else {
ASTNodeProperty property = declName.getPropertyInParent();
if (property == IASTCompositeTypeSpecifier.TYPE_NAME
|| property == ICPPASTEnumerationSpecifier.ENUMERATION_NAME && ((ICPPASTEnumerationSpecifier) declName.getParent()).isScoped()) {
while (declName instanceof ICPPASTTemplateId) {
declName = ((ICPPASTTemplateId) declName).getTemplateName();
}
IBinding binding = declName.resolveBinding();
if (binding instanceof IProblemBinding)
return true;
if (binding instanceof ICPPInternalBinding) {
IASTNode[] declarations = ((ICPPInternalBinding) binding).getDeclarations();
if (declarations != null && declarations.length != 0) {
IASTNode firstDeclaration = declarations[0];
int firstDeclarationOffset = ASTNodes.offset(firstDeclaration);
if (startOffset > firstDeclarationOffset) {
startPoint = firstDeclaration;
startOffset = firstDeclarationOffset;
}
}
}
}
}
for (IASTName name : names) {
if (name != declName) {
char[] nameChars = name.getSimpleID();
int offset = nameChars.length != 0 && nameChars[0] == '~' ? 1 : 0;
if (CharArrayUtils.equals(nameChars, offset, nameChars.length - offset, declNameChars)
&& (ASTNodes.offset(name) >= startOffset
|| isInsideTemplateDeclarationOrSpecialization(name))) {
return true;
}
}
}
}
return false;
};
private static Collection<IASTName> getDeclaredNames(IASTDeclaration declaration) {
while (declaration instanceof ICPPASTTemplateDeclaration) {
declaration = ((ICPPASTTemplateDeclaration) declaration).getDeclaration();
}
while (declaration instanceof ICPPASTTemplateSpecialization) {
declaration = ((ICPPASTTemplateSpecialization) declaration).getDeclaration();
}
while (declaration instanceof ICPPASTExplicitTemplateInstantiation) {
declaration = ((ICPPASTExplicitTemplateInstantiation) declaration).getDeclaration();
}
if (declaration instanceof IASTSimpleDeclaration) {
List<IASTName> names = new ArrayList<>();
IASTDeclarator[] declarators = ((IASTSimpleDeclaration) declaration).getDeclarators();
for (IASTDeclarator declarator : declarators) {
declarator = findInnermostDeclarator(declarator);
IASTName name = declarator.getName();
if (name instanceof ICPPASTConversionName)
return null; // Do not remove conversion operators.
names.add(name);
}
IASTDeclSpecifier declSpecifier = ((IASTSimpleDeclaration) declaration).getDeclSpecifier();
if (declSpecifier instanceof IASTCompositeTypeSpecifier) {
names.add(((IASTCompositeTypeSpecifier) declSpecifier).getName());
} else if (declSpecifier instanceof IASTElaboratedTypeSpecifier) {
names.add(((IASTElaboratedTypeSpecifier) declSpecifier).getName());
} else if (declSpecifier instanceof IASTEnumerationSpecifier) {
names.add(((IASTEnumerationSpecifier) declSpecifier).getName());
}
return names;
} else if (declaration instanceof IASTFunctionDefinition) {
IASTDeclarator declarator = ((IASTFunctionDefinition) declaration).getDeclarator();
declarator = findInnermostDeclarator(declarator);
IASTName name = declarator.getName();
if (name instanceof ICPPASTConversionName)
return null; // Do not remove conversion operators.
return Collections.singletonList(name);
} else if (declaration instanceof ICPPASTUsingDirective) {
return Collections.singletonList(((ICPPASTUsingDirective) declaration).getQualifiedName());
} else if (declaration instanceof ICPPASTUsingDeclaration) {
return Collections.singletonList(((ICPPASTUsingDeclaration) declaration).getName());
} else if (declaration instanceof ICPPASTNamespaceAlias) {
return Collections.singletonList(((ICPPASTNamespaceAlias) declaration).getAlias());
} else if (declaration instanceof ICPPASTAliasDeclaration) {
return Collections.singletonList(((ICPPASTAliasDeclaration) declaration).getAlias());
}
return null;
}
private static boolean isInsideTemplateDeclarationOrSpecialization(IASTNode node) {
while ((node = node.getParent()) != null) {
if (node instanceof ICPPASTTemplateDeclaration || node instanceof ICPPASTTemplateSpecialization)
return true;
}
return false;
}
private static void removeContainedNames(IASTNode node, Set<IASTName> names) {
NavigableSet<IASTName> containedNames = NameCollector.getContainedNames(node);
names.removeAll(containedNames);
}
private static int skipWhitespaceBefore(int offset, String text) {
while (--offset >= 0) {
char c = text.charAt(offset);
if (!Character.isWhitespace(c))
break;
}
return offset + 1;
}
@Override
protected void collectModifications(IProgressMonitor pm, ModificationCollector collector)
throws CoreException, OperationCanceledException {
// This method is no-op for this refactoring. The change is created in the createChange method.
}
private class CandidateDeclarationFinder extends ASTVisitor {
final List<IASTDeclaration> declarations = new ArrayList<>();
CandidateDeclarationFinder() {
shouldVisitDeclarations = true;
shouldVisitNamespaces = true;
}
@Override
public int visit(IASTDeclaration declaration) {
if (!declaration.isPartOfTranslationUnitFile())
return PROCESS_SKIP;
if (declaration.getParent() instanceof IASTDeclarationListOwner)
declarations.add(declaration);
return PROCESS_CONTINUE;
}
@Override
public int visit(ICPPASTNamespaceDefinition namespaceDefinition) {
if (!namespaceDefinition.isPartOfTranslationUnitFile())
return PROCESS_SKIP;
declarations.add(namespaceDefinition);
return PROCESS_CONTINUE;
}
}
/**
* Collects all simple names.
*/
private static class NameCollector extends ASTVisitor {
NavigableSet<IASTName> names = new SortedNodeSet<>();
static NavigableSet<IASTName> getContainedNames(IASTNode node) {
NameCollector collector = new NameCollector();
node.accept(collector);
return collector.names;
}
NameCollector() {
this.shouldVisitNames = true;
this.shouldVisitImplicitNames = true;
}
@Override
public int visit(IASTName name) {
if (name instanceof ICPPASTQualifiedName || name instanceof ICPPASTTemplateId
|| name instanceof ICPPASTConversionName) {
return PROCESS_CONTINUE;
}
names.add(name);
return PROCESS_CONTINUE;
}
}
/**
* A set of AST nodes sorted by their offsets, or, if the offsets are equal, by the end offsets
* in the reverse order.
*/
private static class SortedNodeSet<T extends IASTNode> extends TreeSet<T> {
private static final Comparator<IASTNode> COMPARATOR = new Comparator<IASTNode>() {
@Override
public int compare(IASTNode node1, IASTNode node2) {
int c = Integer.compare(ASTNodes.offset(node1), ASTNodes.offset(node2));
if (c != 0)
return c;
return -Integer.compare(ASTNodes.endOffset(node1), ASTNodes.endOffset(node2));
}
};
public SortedNodeSet() {
super(COMPARATOR);
}
}
private static IASTDeclarationStatement getDeclarationStatement(IASTDeclaration declaration) {
while (true) {
IASTNode parent = declaration.getParent();
if (parent instanceof IASTDeclarationStatement)
return (IASTDeclarationStatement) parent;
if (!(parent instanceof ICPPASTTemplateDeclaration))
return null;
declaration = (IASTDeclaration) parent;
}
}
private static IASTName getAstName(IASTDeclarator decl) {
IASTName astName = null;
do {
astName = decl.getName();
if (astName != null && astName.getSimpleID().length != 0)
return astName;
// Resolve parenthesis if need to.
decl = decl.getNestedDeclarator();
} while (decl != null);
return astName;
}
@Override
protected RefactoringDescriptor getRefactoringDescriptor() {
return null;
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringSaveHelper;
public class RemoveUnusedDeclarationsRefactoringRunner extends RefactoringRunner {
public RemoveUnusedDeclarationsRefactoringRunner(ICElement element, ISelection selection,
IShellProvider shellProvider, ICProject cProject) {
super(element, selection, shellProvider, cProject);
}
@Override
public void run() {
RemoveUnusedDeclarationsRefactoring refactoring =
new RemoveUnusedDeclarationsRefactoring(element, selection, project);
RemoveUnusedDeclarationsWizard wizard = new RemoveUnusedDeclarationsWizard(refactoring);
run(wizard, refactoring, RefactoringSaveHelper.SAVE_NOTHING);
}
}

View file

@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2016 Google, 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
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.reducer;
import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
import org.eclipse.cdt.ui.CUIPlugin;
public class RemoveUnusedDeclarationsWizard extends RefactoringWizard {
public RemoveUnusedDeclarationsWizard(RemoveUnusedDeclarationsRefactoring refactoring) {
super(refactoring, DIALOG_BASED_USER_INTERFACE | PREVIEW_EXPAND_FIRST_NODE);
setDefaultPageTitle(Messages.RemoveFunctionBodiesRefactoring_RemoveFunctionBodies);
setDialogSettings(CUIPlugin.getDefault().getDialogSettings());
}
@Override
protected void addUserInputPages() {
}
}

View file

@ -13,6 +13,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.utils;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.viewers.ISelection;
@ -43,9 +44,9 @@ public class SelectionHelper {
return null;
}
public static IASTSimpleDeclaration findFirstSelectedDeclaration(final Region textSelection,
public static IASTSimpleDeclaration findFirstSelectedDeclaration(final IRegion textSelection,
IASTTranslationUnit translationUnit) {
final Container<IASTSimpleDeclaration> container = new Container<IASTSimpleDeclaration>();
final Container<IASTSimpleDeclaration> container = new Container<>();
translationUnit.accept(new ASTVisitor() {
{
@ -64,18 +65,18 @@ public class SelectionHelper {
return container.getObject();
}
public static boolean doesNodeOverlapWithRegion(IASTNode node, Region region) {
public static boolean doesNodeOverlapWithRegion(IASTNode node, IRegion region) {
return doRegionsOverlap(getNodeSpan(node), region);
}
public static boolean isNodeInsideRegion(IASTNode node, Region region) {
public static boolean isNodeInsideRegion(IASTNode node, IRegion region) {
return isRegionInside(getNodeSpan(node), region);
}
/**
* Returns true if the first region is inside the second.
*/
private static boolean isRegionInside(Region region1, Region region2) {
private static boolean isRegionInside(IRegion region1, IRegion region2) {
int offset1 = region1.getOffset();
int offset2 = region2.getOffset();
return offset1 >= offset2 &&
@ -85,26 +86,26 @@ public class SelectionHelper {
/**
* Returns true if the two regions have at least one common point.
*/
private static boolean doRegionsOverlap(Region region1, Region region2) {
private static boolean doRegionsOverlap(IRegion region1, IRegion region2) {
int offset1 = region1.getOffset();
int offset2 = region2.getOffset();
return offset1 + region1.getLength() >= offset2 &&
offset1 <= offset2 + region2.getLength();
}
public static boolean isNodeInsideSelection(IASTNode node, Region selection) {
public static boolean isNodeInsideSelection(IASTNode node, IRegion selection) {
return node.isPartOfTranslationUnitFile() && isNodeInsideRegion(node, selection);
}
public static boolean isSelectionInsideNode(IASTNode node, Region selection) {
public static boolean isSelectionInsideNode(IASTNode node, IRegion selection) {
return node.isPartOfTranslationUnitFile() && isRegionInside(selection, getNodeSpan(node));
}
public static boolean nodeMatchesSelection(IASTNode node, Region region) {
public static boolean nodeMatchesSelection(IASTNode node, IRegion region) {
return getNodeSpan(node).equals(region);
}
protected static Region getNodeSpan(IASTNode region) {
protected static IRegion getNodeSpan(IASTNode region) {
int start = Integer.MAX_VALUE;
int nodeLength = 0;
IASTNodeLocation[] nodeLocations = region.getNodeLocations();