Bug 521243: [JUnit 5] Find workarounds in place of bug 502563

Change-Id: Ie100cc2ac55a771ba27181f1bf4c339ee6dd5bea
diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java
index 70b3842..7f6829e 100644
--- a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java
+++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/corext/util/JavaModelUtil.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -449,6 +449,19 @@
 	 * @throws JavaModelException thrown when the type can not be accessed
 	 */
 	public static String getResolvedTypeName(String refTypeSig, IType declaringType) throws JavaModelException {
+		return getResolvedTypeName(refTypeSig, declaringType, '.');
+	}
+
+	/**
+	 * Resolves a type name in the context of the declaring type.
+	 *
+	 * @param refTypeSig the type name in signature notation (for example 'QVector') this can also be an array type, but dimensions will be ignored.
+	 * @param declaringType the context for resolving (type where the reference was made in)
+	 * @param enclosingTypeSeparator the enclosing type separator used in the qualified type name 
+	 * @return returns the fully qualified type name or build-in-type name. if a unresolved type couldn't be resolved null is returned
+	 * @throws JavaModelException thrown when the type can not be accessed
+	 */
+	public static String getResolvedTypeName(String refTypeSig, IType declaringType, char enclosingTypeSeparator) throws JavaModelException {
 		int arrayCount= Signature.getArrayCount(refTypeSig);
 		char type= refTypeSig.charAt(arrayCount);
 		if (type == Signature.C_UNRESOLVED) {
@@ -465,7 +478,7 @@
 			}
 			String[][] resolvedNames= declaringType.resolveType(name);
 			if (resolvedNames != null && resolvedNames.length > 0) {
-				return JavaModelUtil.concatenateName(resolvedNames[0][0], resolvedNames[0][1]);
+				return JavaModelUtil.concatenateName(resolvedNames[0][0], resolvedNames[0][1].replace('.', enclosingTypeSeparator));
 			}
 			return null;
 		} else {
diff --git a/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/launcher/JUnitLaunchConfigurationTab.java b/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/launcher/JUnitLaunchConfigurationTab.java
index cf3eeb3..e7d14c6 100644
--- a/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/launcher/JUnitLaunchConfigurationTab.java
+++ b/org.eclipse.jdt.junit/src/org/eclipse/jdt/junit/launcher/JUnitLaunchConfigurationTab.java
@@ -15,7 +15,6 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
@@ -91,7 +90,7 @@
 import org.eclipse.jdt.core.search.IJavaSearchScope;
 import org.eclipse.jdt.core.search.SearchEngine;
 
-import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
+import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
 import org.eclipse.jdt.internal.junit.BasicElementLabels;
 import org.eclipse.jdt.internal.junit.JUnitCorePlugin;
 import org.eclipse.jdt.internal.junit.Messages;
@@ -747,18 +746,63 @@
 		}
 	}
 
-	static String getParameterTypes(IMethod method, boolean useSimpleNames) {
+	/**
+	 * Returns a comma-separated list of method parameter type names in parentheses or "" if the method
+	 * has no parameters. If fully qualified type names are required, <code>$</code> is used as the
+	 * enclosing type separator in the qualified type name. Type erasure is performed on a parameterized
+	 * type, arrays use the square brackets and a type parameter is resolved while creating the return
+	 * value.
+	 * 
+	 * @param method the method whose parameter types are required
+	 * @param useSimpleNames <code>true</code> if the last segment of the type name should be used
+	 *            instead of the fully qualified type name
+	 * @return a comma-separated list of method parameter type names in parentheses
+	 */
+	static String getParameterTypes(final IMethod method, final boolean useSimpleNames) {
 		String paramTypes= ""; //$NON-NLS-1$
-		if (method.getNumberOfParameters() > 0) {
-			// TODO - JUnit5: needs fully qualified type names for the parameter types (check int[] etc.) 
-			// use new API from jdt.core - https://bugs.eclipse.org/bugs/show_bug.cgi?id=502563
-			String[] parameterTypeNames= StubUtility.getParameterTypeNamesForSeeTag(method);
-			Stream<String> stream= Arrays.stream(parameterTypeNames);
+
+		int numOfParams= method.getNumberOfParameters();
+		if (numOfParams > 0) {
+			String[] parameterTypeSignatures= method.getParameterTypes();
+			ArrayList<String> parameterTypeNames= new ArrayList<>(numOfParams);
+
+			try {
+				String[] fullNames= null;
+				for (int i= 0; i < parameterTypeSignatures.length; i++) {
+					String paramTypeSign= parameterTypeSignatures[i];
+					StringBuffer buf= new StringBuffer();
+
+					String typeSign= Signature.getTypeErasure(paramTypeSign);
+					String fullName= JavaModelUtil.getResolvedTypeName(typeSign, method.getDeclaringType(), '$');
+					if (fullName == null) { // e.g. a type parameter "QE;"
+						if (fullNames == null) {
+							fullNames= JUnitStubUtility.getParameterTypeNamesForSeeTag(method);
+						}
+						fullName= fullNames[i];
+					}
+
+					if (fullName != null) {
+						buf.append(fullName);
+						int dim= Signature.getArrayCount(typeSign);
+						while (dim > 0) {
+							buf.append("[]"); //$NON-NLS-1$
+							dim--;
+						}
+					}
+
+					parameterTypeNames.add(buf.toString());
+				}
+			} catch (JavaModelException e) {
+				// ignore
+			}
+
+			Stream<String> stream= parameterTypeNames.stream();
 			if (useSimpleNames) {
 				stream= stream.map(paramTypeName -> paramTypeName.substring(paramTypeName.lastIndexOf('.') + 1));
 			}
 			paramTypes= stream.collect(Collectors.joining(", ", "(", ")")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$	
 		}
+
 		return paramTypes;
 	}
 
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility.java
index 591cfd3..cea8de8 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -331,7 +331,7 @@
 	/*
 	 * Returns the parameters type names used in see tags. Currently, these are always fully qualified.
 	 */
-	public static String[] getParameterTypeNamesForSeeTag(IMethod overridden) {
+	private static String[] getParameterTypeNamesForSeeTag(IMethod overridden) {
 		try {
 			ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
 			parser.setProject(overridden.getJavaProject());