| /********************************************************************** |
| * This file is part of "Object Teams Development Tooling"-Software |
| * |
| * Copyright 2008, 2017 Technical University Berlin, Germany and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Please visit http://www.eclipse.org/objectteams for updates and contact. |
| * |
| * Contributors: |
| * Technical University Berlin - Initial API and implementation |
| **********************************************************************/ |
| package org.eclipse.objectteams.otdt.internal.debug.adaptor; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.debug.core.IJavaType; |
| import org.eclipse.jdt.internal.compiler.util.SuffixConstants; |
| import org.eclipse.objectteams.otdt.core.compiler.IOTConstants; |
| |
| import base org.eclipse.jdt.internal.debug.core.JavaDebugUtils; |
| |
| /** |
| * This team makes the PDE source lookup aware of role files. |
| * |
| * @author stephan |
| * @since 1.2.1 |
| */ |
| @SuppressWarnings("restriction") |
| public team class SourceLookupAdaptor { |
| |
| /** |
| * Fix source lookup for "Open Actual Type" action for special OT types: |
| * <ul> |
| * <li>"$__OT__" delimiters are removed from role names for successful lookup of ITypes.</li> |
| * <li>Find role files in the proper team package.</li> |
| * <li>Find the most specific source for phantom roles.</li> |
| * </ul> |
| */ |
| protected class JavaDebugUtils playedBy JavaDebugUtils |
| { |
| IJavaElement getJavaElement(Object sourceElement) -> IJavaElement getJavaElement(Object sourceElement); |
| |
| Object resolveSourceElement(Object object, String stratum, ILaunch launch) -> Object resolveSourceElement(Object object, String stratum, ILaunch launch); |
| |
| @SuppressWarnings("decapsulation") |
| IType resolveType(String qualifiedName, IJavaElement javaElement) <- replace IType resolveType(String qualifiedName, IJavaElement javaElement); |
| |
| static callin IType resolveType(String qualifiedName, IJavaElement javaElement) { |
| qualifiedName = qualifiedName.replace("$__OT__", "$"); //$NON-NLS-1$ //$NON-NLS-2$ |
| IType result = base.resolveType(qualifiedName, javaElement); |
| if (result != null && (result.exists() || isSyntheticName(qualifiedName))) |
| return result; |
| // the given compilation unit doesn't have a type `type.getName()` |
| try { |
| ICompilationUnit resolvedCU = (ICompilationUnit) javaElement; |
| return findRoFiOrTSuper(qualifiedName, resolvedCU); |
| } catch (Exception e) { |
| // nothing found |
| } |
| return null; |
| } |
| |
| private static boolean isSyntheticName(String qualifiedName) { |
| int lastDot = qualifiedName.lastIndexOf('.'); |
| if (lastDot == -1) |
| return false; |
| String lastSegment = qualifiedName.substring(lastDot+1); |
| try { |
| Integer.parseInt(lastSegment); |
| return true; |
| } catch (NumberFormatException e) { |
| return false; |
| } |
| } |
| |
| static IType findRoFiOrTSuper(String qualifiedName, ICompilationUnit resolvedCU) throws JavaModelException { |
| int lastDollar = qualifiedName.lastIndexOf('$'); |
| if (lastDollar != -1) { |
| String roleName = qualifiedName.substring(lastDollar+1); |
| IJavaProject javaProject = resolvedCU.getJavaProject(); |
| |
| // check for role file: |
| IPackageFragment pack = (IPackageFragment) resolvedCU.getParent(); |
| int start = 0; |
| int currentDollar; |
| while ((currentDollar = qualifiedName.indexOf('$', start)) != -1) { |
| String teamPackName = qualifiedName.substring(0, currentDollar); // include at least one type name |
| if (pack.getElementName().equals(teamPackName)) { |
| return getTypeInPackage(pack, qualifiedName.substring(currentDollar+1)); |
| } |
| start = currentDollar+1; |
| } |
| |
| // find a type that is (a) tsuper of `type` (search via superclass of enclosing) and (b) exists |
| String enclosingName = qualifiedName.substring(0, lastDollar); |
| IType enclosingType = javaProject.findType(enclosingName); |
| while (enclosingType != null) { |
| IType type = enclosingType.getType(roleName); |
| if (type.exists()) |
| return type; |
| String[][] superclassName = enclosingType.resolveType((enclosingType.getSuperclassName())); |
| try { |
| enclosingType = javaProject.findType(superclassName[0][0], superclassName[0][1]); |
| } catch (JavaModelException jme) { |
| if (jme.isDoesNotExist()) { |
| enclosingType = findRoFiOrTSuper(enclosingName, resolvedCU); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| } |
| private static IType getTypeInPackage(IPackageFragment pack, String relativeName) { |
| int firstDollar = relativeName.indexOf('$'); |
| String cuName = firstDollar == -1 ? relativeName : relativeName.substring(0, firstDollar); |
| ICompilationUnit unit = pack.getCompilationUnit(cuName + SuffixConstants.SUFFIX_STRING_java); |
| if (unit.exists()) { |
| IType top = unit.getType(cuName); |
| if (top.exists() && firstDollar != -1) |
| return findMemberType(top, relativeName.substring(firstDollar+1)); |
| return top; |
| } |
| return null; |
| } |
| private static IType findMemberType(IType type, String memberName) { |
| int firstDollar = memberName.indexOf('$'); |
| if (firstDollar == -1) { |
| return type.getType(memberName); |
| } |
| return findMemberType(type.getType(memberName.substring(0, firstDollar)), memberName.substring(firstDollar)+1); |
| } |
| } |