/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * 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: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.plugin.java.server; import com.google.inject.Singleton; import org.eclipse.che.dto.server.DtoFactory; import org.eclipse.che.ide.ext.java.shared.dto.model.MethodParameters; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.Flags; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.ILocalVariable; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeHierarchy; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.ui.JavaElementLabels; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.eclipse.jdt.core.IJavaElement.METHOD; /** * The class provides business logic which allows to find hints of method's parameters. Also it finds methods parameter hints in * super classes. The class represents founded parameters as ordinary string. Parameters in string separated by coma from each other. * Example: * <pre> * class Test{ * void x(int x, double y); * } * * class Test2 extends Test { * void x(String y); * } * * Test2 test2 = new Test2(); * test2.x(); * </pre> * <p/> * When we call method {@link ParametersHints#findHints(IJavaProject, String, int, int)} for test2.x() * we will get following: * ________ * int x, double y * String y * -------- * * @author Dmitry Shnurenko */ @Singleton public class ParametersHints { public List<MethodParameters> findHints(IJavaProject project, String fqn, int offset, int lineStartOffset) throws JavaModelException { IType type = project.findType(fqn); if (type.isBinary()) { return Collections.emptyList(); } IJavaElement element = getSelectedElement(type, offset, lineStartOffset); if (element == null) { return Collections.emptyList(); } IJavaElement parent = element.getParent(); if (!(parent instanceof IType) || !(element.getElementType() == METHOD)) { return Collections.emptyList(); } List<MethodParameters> result = new ArrayList<>(); findHintsRecursive(element, parent, result); return result; } private IJavaElement getSelectedElement(IType type, int offset, int lineStartOffset) throws JavaModelException { if (offset <= lineStartOffset) { return null; } ICompilationUnit compilationUnit = type.getCompilationUnit(); IJavaElement[] javaElements = compilationUnit.codeSelect(offset, 0); if (javaElements.length == 0) { return getSelectedElement(type, --offset, lineStartOffset); } IJavaElement element = javaElements[0]; if (element.getElementType() == METHOD) { return element; } return getSelectedElement(type, --offset, lineStartOffset); } private void findHintsRecursive(IJavaElement method, IJavaElement parent, List<MethodParameters> result) throws JavaModelException { findHints(method, parent, result); IType type = (IType)parent; ITypeHierarchy typeHierarchy = type.newTypeHierarchy(new NullProgressMonitor()); IType[] superTypes = typeHierarchy.getAllSupertypes(type); for (IType iType : superTypes) { findHintsRecursive(method, iType, result); } } private void findHints(IJavaElement method, IJavaElement parent, List<MethodParameters> result) throws JavaModelException { String methodName = method.getElementName(); for (IMethod iMethod : ((IType)parent).getMethods()) { int methodFlag = iMethod.getFlags(); if (Flags.isPrivate(methodFlag) || !methodName.equals(iMethod.getElementName())) { continue; } MethodParameters methodParameters = DtoFactory.newDto(MethodParameters.class); String parameters = getMethodParametersAsString(iMethod); methodParameters.setMethodName(methodName); methodParameters.setParameters(parameters); if (!result.contains(methodParameters)) { result.add(methodParameters); } } } private String getMethodParametersAsString(IMethod method) throws JavaModelException { ILocalVariable[] parameters = method.getParameters(); int paramsLength = parameters.length; int index = 0; StringBuffer buffer = new StringBuffer(); for (ILocalVariable parameter : parameters) { JavaElementLabels.getLocalVariableLabel(parameter, JavaElementLabels.F_PRE_TYPE_SIGNATURE, buffer); index++; if (index < paramsLength) { buffer.append(", "); } } return buffer.toString(); } }