org.eclipse.core.tools.search.FindUnusedMembers.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.core.tools.search.FindUnusedMembers.java

Source

/*******************************************************************************
 * Copyright (c) 2005 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
 *******************************************************************************/
package org.eclipse.core.tools.search;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.core.search.*;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;

/*
 * Class that removes field declarations which aren't referenced.
 */
public class FindUnusedMembers implements IRunnableWithProgress {

    public static interface IResultReporter {
        void unusedElementFound(IMember member) throws CoreException;
    }

    public static class OutputWriter implements IResultReporter {

        private final Writer output;
        private IType lastType;

        public OutputWriter(Writer writer) {
            output = writer;
        }

        /* (non-Javadoc)
         * @see org.eclipse.core.tools.search.FindUnusedMembers.IResultReporter#unusedElementFound(org.eclipse.jdt.core.IMethod)
         */
        public void unusedElementFound(IMember member) throws CoreException {
            try {
                if (!member.getDeclaringType().equals(lastType)) {
                    lastType = member.getDeclaringType();
                    writeHeader(lastType);
                }
                if (member instanceof IMethod) {
                    writeResult((IMethod) member);
                } else if (member instanceof IField) {
                    writeResult((IField) member);
                }
            } catch (IOException e) {
                // to do
            }
        }

        private void writeHeader(IType type) throws IOException {
            output.write("\n\n" + type.getFullyQualifiedName()); //$NON-NLS-1$
        }

        private void writeResult(IField field) throws IOException, JavaModelException {
            output.write("\n\t"); //$NON-NLS-1$
            output.write(Signature.toString(field.getTypeSignature()));
            output.write(" "); //$NON-NLS-1$
            output.write(field.getElementName());
        }

        private void writeResult(IMethod method) throws IOException, JavaModelException {
            output.write("\n\t");//$NON-NLS-1$
            output.write(Signature.toString(method.getReturnType()));
            output.write(" "); //$NON-NLS-1$
            output.write(method.getElementName());
            output.write("("); //$NON-NLS-1$
            String[] types = method.getParameterTypes();
            for (int i = 0; i < types.length; i++) {
                output.write(Signature.toString(types[i]));
                if (i < types.length - 1)
                    output.write(","); //$NON-NLS-1$
            }
            output.write(")"); //$NON-NLS-1$
        }
    }

    private final IResultReporter result;
    private ICompilationUnit[] units;
    protected int unusedMemberCount = 0;

    public FindUnusedMembers(ICompilationUnit[] units, Writer writer) {
        this(units, new OutputWriter(writer));
    }

    public FindUnusedMembers(ICompilationUnit[] units, IResultReporter resultReporter) {
        this.units = units;
        this.result = resultReporter;
    }

    private void doSearchCU(ICompilationUnit cu, IProgressMonitor monitor) throws CoreException {
        IType[] allTypes = cu.getAllTypes();
        monitor.beginTask("Processing " + cu.getElementName(), allTypes.length + 1); //$NON-NLS-1$
        try {

            ASTParser astParser = ASTParser.newParser(AST.JLS3);
            astParser.setResolveBindings(true);
            astParser.setProject(cu.getJavaProject());

            IBinding[] bindings = astParser.createBindings(allTypes, new NullProgressMonitor());
            for (int i = 0; i < bindings.length; i++) {
                if (monitor.isCanceled())
                    throw new OperationCanceledException();
                ITypeBinding typeBinding = (ITypeBinding) bindings[i];
                monitor.subTask("Processing '" + typeBinding.getQualifiedName() + "'"); //$NON-NLS-1$//$NON-NLS-2$
                doSearchType(typeBinding, new NullProgressMonitor());
            }
        } finally {
            monitor.done();
        }
    }

    private boolean methodOverrides(IMethodBinding binding) {
        return Bindings.findOverriddenMethod(binding, true) != null;
    }

    public void doSearchType(ITypeBinding typeBinding, IProgressMonitor monitor) throws CoreException {
        IMethodBinding[] methods = typeBinding.getDeclaredMethods();
        IVariableBinding[] fields = typeBinding.getDeclaredFields();

        monitor.beginTask("Searching for references.", methods.length + fields.length); //$NON-NLS-1$

        try {
            for (int i = 0; i < methods.length; i++) {
                if (monitor.isCanceled())
                    throw new OperationCanceledException();

                IMethodBinding methodBinding = methods[i];
                if (methodOverrides(methodBinding))
                    continue;

                IMethod method = (IMethod) methodBinding.getJavaElement();
                if (method == null)
                    continue;

                if (hasReferences(method, new SubProgressMonitor(monitor, 1)))
                    continue;
                result.unusedElementFound(method);
                unusedMemberCount++;
            }
            for (int i = 0; i < fields.length; i++) {
                if (monitor.isCanceled())
                    throw new OperationCanceledException();

                IVariableBinding fieldBinding = fields[i];
                IField field = (IField) fieldBinding.getJavaElement();
                if (field == null)
                    continue;
                if (hasReferences(field, new SubProgressMonitor(monitor, 1)))
                    continue;
                result.unusedElementFound(field);
                unusedMemberCount++;
            }

            if (monitor.isCanceled())
                throw new OperationCanceledException();
        } finally {
            monitor.done();
        }
    }

    public int getUnusedMethodCount() {
        return unusedMemberCount;
    }

    private boolean hasReferences(IMember member, IProgressMonitor monitor) throws JavaModelException {

        final class ReferenceFound extends Error {
            private static final long serialVersionUID = 1L;
        }

        try {
            IJavaSearchScope searchScope = RefactoringScopeFactory.create(member.getDeclaringType());
            SearchPattern pattern = SearchPattern.createPattern(member, IJavaSearchConstants.REFERENCES);
            SearchRequestor requestor = new SearchRequestor() {
                public void acceptSearchMatch(SearchMatch match) throws CoreException {
                    if (match.getAccuracy() == SearchMatch.A_ACCURATE) {
                        throw new ReferenceFound();
                    }
                }
            };
            new SearchEngine().search(pattern,
                    new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, searchScope, requestor,
                    monitor);
        } catch (CoreException e) {
            throw new JavaModelException(e);
        } catch (ReferenceFound e) {
            return true;
        }
        return false;
    }

    public void process(IProgressMonitor monitor) throws CoreException {
        if (monitor == null)
            monitor = new NullProgressMonitor();
        try {
            monitor.beginTask("Searching unused members", this.units.length); //$NON-NLS-1$
            for (int i = 0; i < this.units.length; i++) {
                doSearchCU(units[i], new SubProgressMonitor(monitor, 1));
            }
        } finally {
            monitor.done();
        }
    }

    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
        try {
            process(monitor);
        } catch (OperationCanceledException e) {
            throw new InterruptedException();
        } catch (CoreException e) {
            throw new InvocationTargetException(e);
        }
    }

}