PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/at.bestsolution.bitbucketmgr.jdt.editor/src/at/bestsolution/bitbucketmgr/jdt/editor/fork/internal/coreext/util/JavaModelUtil.java

https://bitbucket.org/tschindl/bitbucketmgr
Java | 937 lines | 544 code | 82 blank | 311 comment | 199 complexity | ab1d7e0308e53c69cf5f5cb9830d1f88 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2012 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. * Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic
  11. *******************************************************************************/
  12. package at.bestsolution.bitbucketmgr.jdt.editor.fork.internal.coreext.util;
  13. import java.util.Arrays;
  14. import java.util.HashSet;
  15. import java.util.Map;
  16. import org.eclipse.core.runtime.Assert;
  17. import org.eclipse.core.runtime.CoreException;
  18. import org.eclipse.core.runtime.IPath;
  19. import org.eclipse.core.runtime.IProgressMonitor;
  20. import org.eclipse.core.runtime.IStatus;
  21. import org.eclipse.core.runtime.NullProgressMonitor;
  22. import org.eclipse.core.runtime.Path;
  23. import org.eclipse.core.runtime.SubProgressMonitor;
  24. import org.eclipse.core.resources.IFile;
  25. import org.eclipse.core.resources.IResource;
  26. import org.eclipse.core.resources.IStorage;
  27. import org.eclipse.text.edits.TextEdit;
  28. import org.eclipse.jdt.core.ClasspathContainerInitializer;
  29. import org.eclipse.jdt.core.Flags;
  30. import org.eclipse.jdt.core.IClasspathContainer;
  31. import org.eclipse.jdt.core.IClasspathEntry;
  32. import org.eclipse.jdt.core.ICompilationUnit;
  33. import org.eclipse.jdt.core.IField;
  34. import org.eclipse.jdt.core.IJarEntryResource;
  35. import org.eclipse.jdt.core.IJavaElement;
  36. import org.eclipse.jdt.core.IJavaProject;
  37. import org.eclipse.jdt.core.IMember;
  38. import org.eclipse.jdt.core.IMethod;
  39. import org.eclipse.jdt.core.IPackageFragment;
  40. import org.eclipse.jdt.core.IPackageFragmentRoot;
  41. import org.eclipse.jdt.core.IType;
  42. import org.eclipse.jdt.core.ITypeHierarchy;
  43. import org.eclipse.jdt.core.JavaCore;
  44. import org.eclipse.jdt.core.JavaModelException;
  45. import org.eclipse.jdt.core.Signature;
  46. import org.eclipse.jdt.core.compiler.CharOperation;
  47. import org.eclipse.jdt.launching.IVMInstall;
  48. import org.eclipse.jdt.launching.IVMInstall2;
  49. import org.eclipse.jdt.launching.JavaRuntime;
  50. import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
  51. import at.bestsolution.bitbucketmgr.jdt.editor.fork.internal.coreext.CorextMessages;
  52. import at.bestsolution.bitbucketmgr.jdt.editor.fork.internal.coreext.SuperTypeHierarchyCache;
  53. import at.bestsolution.bitbucketmgr.jdt.editor.fork.internal.coreext.ValidateEditException;
  54. /**
  55. * Utility methods for the Java Model.
  56. */
  57. public final class JavaModelUtil {
  58. /**
  59. * The latest available {@link JavaCore}{@code #VERSION_*} level.
  60. * @since 3.7
  61. */
  62. public static final String VERSION_LATEST;
  63. static {
  64. VERSION_LATEST= JavaCore.VERSION_1_7; // make sure it is not inlined
  65. }
  66. /**
  67. * Only use this suffix for creating new .java files.
  68. * In general, use one of the three *JavaLike*(..) methods in JavaCore or create
  69. * a name from an existing compilation unit with {@link #getRenamedCUName(ICompilationUnit, String)}
  70. * <p>
  71. * Note: Unlike {@link JavaCore#getJavaLikeExtensions()}, this suffix includes a leading ".".
  72. * </p>
  73. *
  74. * @see JavaCore#getJavaLikeExtensions()
  75. * @see JavaCore#isJavaLikeFileName(String)
  76. * @see JavaCore#removeJavaLikeExtension(String)
  77. * @see #getRenamedCUName(ICompilationUnit, String)
  78. */
  79. public static final String DEFAULT_CU_SUFFIX= ".java"; //$NON-NLS-1$
  80. /**
  81. * The name of the package-info.java file.
  82. * @since 3.8
  83. */
  84. public static final String PACKAGE_INFO_JAVA= "package-info.java"; //$NON-NLS-1$
  85. /**
  86. * Finds a type container by container name.
  87. * The returned element will be of type <code>IType</code> or a <code>IPackageFragment</code>.
  88. * <code>null</code> is returned if the type container could not be found.
  89. * @param jproject The Java project defining the context to search
  90. * @param typeContainerName A dot separated name of the type container
  91. * @return returns the container
  92. * @throws JavaModelException thrown when the project can not be accessed
  93. * @see #getTypeContainerName(IType)
  94. */
  95. public static IJavaElement findTypeContainer(IJavaProject jproject, String typeContainerName) throws JavaModelException {
  96. // try to find it as type
  97. IJavaElement result= jproject.findType(typeContainerName);
  98. if (result == null) {
  99. // find it as package
  100. IPath path= new Path(typeContainerName.replace('.', '/'));
  101. result= jproject.findElement(path);
  102. if (!(result instanceof IPackageFragment)) {
  103. result= null;
  104. }
  105. }
  106. return result;
  107. }
  108. /**
  109. * Finds a type in a compilation unit. Typical usage is to find the corresponding
  110. * type in a working copy.
  111. * @param cu the compilation unit to search in
  112. * @param typeQualifiedName the type qualified name (type name with enclosing type names (separated by dots))
  113. * @return the type found, or null if not existing
  114. * @throws JavaModelException thrown when the cu can not be accessed
  115. */
  116. public static IType findTypeInCompilationUnit(ICompilationUnit cu, String typeQualifiedName) throws JavaModelException {
  117. IType[] types= cu.getAllTypes();
  118. for (int i= 0; i < types.length; i++) {
  119. String currName= types[i].getTypeQualifiedName('.');
  120. if (typeQualifiedName.equals(currName)) {
  121. return types[i];
  122. }
  123. }
  124. return null;
  125. }
  126. /**
  127. * Returns the element of the given compilation unit which is "equal" to the
  128. * given element. Note that the given element usually has a parent different
  129. * from the given compilation unit.
  130. *
  131. * @param cu the cu to search in
  132. * @param element the element to look for
  133. * @return an element of the given cu "equal" to the given element
  134. */
  135. public static IJavaElement findInCompilationUnit(ICompilationUnit cu, IJavaElement element) {
  136. IJavaElement[] elements= cu.findElements(element);
  137. if (elements != null && elements.length > 0) {
  138. return elements[0];
  139. }
  140. return null;
  141. }
  142. /**
  143. * Returns the fully qualified name of a type's container. (package name or enclosing type name)
  144. * @param type the type
  145. * @return the type container name
  146. */
  147. public static String getTypeContainerName(IType type) {
  148. IType outerType= type.getDeclaringType();
  149. if (outerType != null) {
  150. return outerType.getFullyQualifiedName('.');
  151. } else {
  152. return type.getPackageFragment().getElementName();
  153. }
  154. }
  155. /**
  156. * Concatenates two names. Uses a dot for separation.
  157. * Both strings can be empty or <code>null</code>.
  158. * @param name1 the first name
  159. * @param name2 the second name
  160. * @return the concatenated name
  161. */
  162. public static String concatenateName(String name1, String name2) {
  163. StringBuffer buf= new StringBuffer();
  164. if (name1 != null && name1.length() > 0) {
  165. buf.append(name1);
  166. }
  167. if (name2 != null && name2.length() > 0) {
  168. if (buf.length() > 0) {
  169. buf.append('.');
  170. }
  171. buf.append(name2);
  172. }
  173. return buf.toString();
  174. }
  175. /**
  176. * Concatenates two names. Uses a dot for separation.
  177. * Both strings can be empty or <code>null</code>.
  178. * @param name1 the first string
  179. * @param name2 the second string
  180. * @return the concatenated string
  181. */
  182. public static String concatenateName(char[] name1, char[] name2) {
  183. StringBuffer buf= new StringBuffer();
  184. if (name1 != null && name1.length > 0) {
  185. buf.append(name1);
  186. }
  187. if (name2 != null && name2.length > 0) {
  188. if (buf.length() > 0) {
  189. buf.append('.');
  190. }
  191. buf.append(name2);
  192. }
  193. return buf.toString();
  194. }
  195. /**
  196. * Returns whether the two names match. They match if they
  197. * are equal, or if they are the same name but one is missing a dot-separated qualifier.
  198. *
  199. * @param nameA a potentially qualified name
  200. * @param nameB a potentially qualified name
  201. * @return <code>true</code> iff the given names match
  202. * @since 3.8
  203. */
  204. public static boolean isMatchingName(String nameA, String nameB) {
  205. int a= nameA.length();
  206. int b= nameB.length();
  207. if (a == b) {
  208. return nameA.equals(nameB);
  209. } else if (a < b - 1) {
  210. return nameB.endsWith(nameA) && nameB.charAt(b - a - 1) == '.';
  211. } else if (b < a - 1) {
  212. return nameA.endsWith(nameB) && nameA.charAt(a - b - 1) == '.';
  213. } else {
  214. return false;
  215. }
  216. }
  217. /**
  218. * Evaluates if a member (possible from another package) is visible from
  219. * elements in a package.
  220. * @param member The member to test the visibility for
  221. * @param pack The package in focus
  222. * @return returns <code>true</code> if the member is visible from the package
  223. * @throws JavaModelException thrown when the member can not be accessed
  224. */
  225. public static boolean isVisible(IMember member, IPackageFragment pack) throws JavaModelException {
  226. int type= member.getElementType();
  227. if (type == IJavaElement.INITIALIZER || (type == IJavaElement.METHOD && member.getElementName().startsWith("<"))) { //$NON-NLS-1$
  228. return false;
  229. }
  230. int otherflags= member.getFlags();
  231. IType declaringType= member.getDeclaringType();
  232. if (Flags.isPublic(otherflags) || (declaringType != null && isInterfaceOrAnnotation(declaringType))) {
  233. return true;
  234. } else if (Flags.isPrivate(otherflags)) {
  235. return false;
  236. }
  237. IPackageFragment otherpack= (IPackageFragment) member.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
  238. return (pack != null && otherpack != null && isSamePackage(pack, otherpack));
  239. }
  240. /**
  241. * Evaluates if a member in the focus' element hierarchy is visible from
  242. * elements in a package.
  243. * @param member The member to test the visibility for
  244. * @param pack The package of the focus element focus
  245. * @return returns <code>true</code> if the member is visible from the package
  246. * @throws JavaModelException thrown when the member can not be accessed
  247. */
  248. public static boolean isVisibleInHierarchy(IMember member, IPackageFragment pack) throws JavaModelException {
  249. int type= member.getElementType();
  250. if (type == IJavaElement.INITIALIZER || (type == IJavaElement.METHOD && member.getElementName().startsWith("<"))) { //$NON-NLS-1$
  251. return false;
  252. }
  253. int otherflags= member.getFlags();
  254. IType declaringType= member.getDeclaringType();
  255. if (Flags.isPublic(otherflags) || Flags.isProtected(otherflags) || (declaringType != null && isInterfaceOrAnnotation(declaringType))) {
  256. return true;
  257. } else if (Flags.isPrivate(otherflags)) {
  258. return false;
  259. }
  260. IPackageFragment otherpack= (IPackageFragment) member.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
  261. return (pack != null && pack.equals(otherpack));
  262. }
  263. /**
  264. * Returns the package fragment root of <code>IJavaElement</code>. If the given
  265. * element is already a package fragment root, the element itself is returned.
  266. * @param element the element
  267. * @return the package fragment root of the element or <code>null</code>
  268. */
  269. public static IPackageFragmentRoot getPackageFragmentRoot(IJavaElement element) {
  270. return (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
  271. }
  272. /**
  273. * Finds a method in a type.
  274. * This searches for a method with the same name and signature. Parameter types are only
  275. * compared by the simple name, no resolving for the fully qualified type name is done.
  276. * Constructors are only compared by parameters, not the name.
  277. * @param name The name of the method to find
  278. * @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
  279. * @param isConstructor If the method is a constructor
  280. * @param type the type
  281. * @return The first found method or <code>null</code>, if nothing foun
  282. * @throws JavaModelException thrown when the type can not be accessed
  283. */
  284. public static IMethod findMethod(String name, String[] paramTypes, boolean isConstructor, IType type) throws JavaModelException {
  285. IMethod[] methods= type.getMethods();
  286. for (int i= 0; i < methods.length; i++) {
  287. if (isSameMethodSignature(name, paramTypes, isConstructor, methods[i])) {
  288. return methods[i];
  289. }
  290. }
  291. return null;
  292. }
  293. /**
  294. * Finds a method in a type and all its super types. The super class hierarchy is searched first, then the super interfaces.
  295. * This searches for a method with the same name and signature. Parameter types are only
  296. * compared by the simple name, no resolving for the fully qualified type name is done.
  297. * Constructors are only compared by parameters, not the name.
  298. * NOTE: For finding overridden methods or for finding the declaring method, use {@link MethodOverrideTester}
  299. * @param hierarchy The hierarchy containing the type
  300. * @param type The type to start the search from
  301. * @param name The name of the method to find
  302. * @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
  303. * @param isConstructor If the method is a constructor
  304. * @return The first found method or <code>null</code>, if nothing found
  305. * @throws JavaModelException thrown when the type can not be accessed
  306. */
  307. public static IMethod findMethodInHierarchy(ITypeHierarchy hierarchy, IType type, String name, String[] paramTypes, boolean isConstructor) throws JavaModelException {
  308. IMethod method= findMethod(name, paramTypes, isConstructor, type);
  309. if (method != null) {
  310. return method;
  311. }
  312. IType superClass= hierarchy.getSuperclass(type);
  313. if (superClass != null) {
  314. IMethod res= findMethodInHierarchy(hierarchy, superClass, name, paramTypes, isConstructor);
  315. if (res != null) {
  316. return res;
  317. }
  318. }
  319. if (!isConstructor) {
  320. IType[] superInterfaces= hierarchy.getSuperInterfaces(type);
  321. for (int i= 0; i < superInterfaces.length; i++) {
  322. IMethod res= findMethodInHierarchy(hierarchy, superInterfaces[i], name, paramTypes, false);
  323. if (res != null) {
  324. return res;
  325. }
  326. }
  327. }
  328. return method;
  329. }
  330. /**
  331. * Tests if a method equals to the given signature.
  332. * Parameter types are only compared by the simple name, no resolving for
  333. * the fully qualified type name is done. Constructors are only compared by
  334. * parameters, not the name.
  335. * @param name Name of the method
  336. * @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
  337. * @param isConstructor Specifies if the method is a constructor
  338. * @param curr the method
  339. * @return Returns <code>true</code> if the method has the given name and parameter types and constructor state.
  340. * @throws JavaModelException thrown when the method can not be accessed
  341. */
  342. public static boolean isSameMethodSignature(String name, String[] paramTypes, boolean isConstructor, IMethod curr) throws JavaModelException {
  343. if (isConstructor || name.equals(curr.getElementName())) {
  344. if (isConstructor == curr.isConstructor()) {
  345. String[] currParamTypes= curr.getParameterTypes();
  346. if (paramTypes.length == currParamTypes.length) {
  347. for (int i= 0; i < paramTypes.length; i++) {
  348. String t1= Signature.getSimpleName(Signature.toString(paramTypes[i]));
  349. String t2= Signature.getSimpleName(Signature.toString(currParamTypes[i]));
  350. if (!t1.equals(t2)) {
  351. return false;
  352. }
  353. }
  354. return true;
  355. }
  356. }
  357. }
  358. return false;
  359. }
  360. /**
  361. * Tests if two <code>IPackageFragment</code>s represent the same logical java package.
  362. * @param pack1 the first package
  363. * @param pack2 the second package
  364. * @return <code>true</code> if the package fragments' names are equal.
  365. */
  366. public static boolean isSamePackage(IPackageFragment pack1, IPackageFragment pack2) {
  367. return pack1.getElementName().equals(pack2.getElementName());
  368. }
  369. /**
  370. * Checks whether the given type has a valid main method or not.
  371. * @param type the type to test
  372. * @return returns <code>true</code> if the type has a main method
  373. * @throws JavaModelException thrown when the type can not be accessed
  374. */
  375. public static boolean hasMainMethod(IType type) throws JavaModelException {
  376. IMethod[] methods= type.getMethods();
  377. for (int i= 0; i < methods.length; i++) {
  378. if (methods[i].isMainMethod()) {
  379. return true;
  380. }
  381. }
  382. return false;
  383. }
  384. /**
  385. * Checks if the field is boolean.
  386. * @param field the field
  387. * @return returns <code>true</code> if the field returns a boolean
  388. * @throws JavaModelException thrown when the field can not be accessed
  389. */
  390. public static boolean isBoolean(IField field) throws JavaModelException{
  391. return field.getTypeSignature().equals(Signature.SIG_BOOLEAN);
  392. }
  393. /**
  394. * @param type the type to test
  395. * @return <code>true</code> iff the type is an interface or an annotation
  396. * @throws JavaModelException thrown when the field can not be accessed
  397. */
  398. public static boolean isInterfaceOrAnnotation(IType type) throws JavaModelException {
  399. return type.isInterface();
  400. }
  401. /**
  402. * Resolves a type name in the context of the declaring type.
  403. *
  404. * @param refTypeSig the type name in signature notation (for example 'QVector') this can also be an array type, but dimensions will be ignored.
  405. * @param declaringType the context for resolving (type where the reference was made in)
  406. * @return returns the fully qualified type name or build-in-type name. if a unresolved type couldn't be resolved null is returned
  407. * @throws JavaModelException thrown when the type can not be accessed
  408. */
  409. public static String getResolvedTypeName(String refTypeSig, IType declaringType) throws JavaModelException {
  410. int arrayCount= Signature.getArrayCount(refTypeSig);
  411. char type= refTypeSig.charAt(arrayCount);
  412. if (type == Signature.C_UNRESOLVED) {
  413. String name= ""; //$NON-NLS-1$
  414. int bracket= refTypeSig.indexOf(Signature.C_GENERIC_START, arrayCount + 1);
  415. if (bracket > 0)
  416. name= refTypeSig.substring(arrayCount + 1, bracket);
  417. else {
  418. int semi= refTypeSig.indexOf(Signature.C_SEMICOLON, arrayCount + 1);
  419. if (semi == -1) {
  420. throw new IllegalArgumentException();
  421. }
  422. name= refTypeSig.substring(arrayCount + 1, semi);
  423. }
  424. String[][] resolvedNames= declaringType.resolveType(name);
  425. if (resolvedNames != null && resolvedNames.length > 0) {
  426. return JavaModelUtil.concatenateName(resolvedNames[0][0], resolvedNames[0][1]);
  427. }
  428. return null;
  429. } else {
  430. return Signature.toString(refTypeSig.substring(arrayCount));
  431. }
  432. }
  433. /**
  434. * Returns if a CU can be edited.
  435. * @param cu the compilation unit
  436. * @return <code>true</code> if the CU can be edited
  437. */
  438. public static boolean isEditable(ICompilationUnit cu) {
  439. Assert.isNotNull(cu);
  440. IResource resource= cu.getPrimary().getResource();
  441. return (resource.exists() && !resource.getResourceAttributes().isReadOnly());
  442. }
  443. /**
  444. * Returns true if a cu is a primary cu (original or shared working copy)
  445. * @param cu the compilation unit
  446. * @return return <code>true</code> if the CU is primary
  447. */
  448. public static boolean isPrimary(ICompilationUnit cu) {
  449. return cu.getOwner() == null;
  450. }
  451. /**
  452. * Checks whether the given type signature is from a primitive type.
  453. *
  454. * @param typeSignature the type signature string to check
  455. * @return <code>true</code> if the type is a primitive type, <code> false</code> otherwise
  456. * @throws JavaModelException if this element does not exist or if an exception occurs while
  457. * accessing its corresponding resource.
  458. * @since 3.7
  459. */
  460. public static boolean isPrimitive(String typeSignature) throws JavaModelException {
  461. return Signature.getTypeSignatureKind(Signature.getElementType(typeSignature)) == Signature.BASE_TYPE_SIGNATURE;
  462. }
  463. /*
  464. * Don't log not-exists exceptions
  465. *
  466. * Also see bug http://bugs.eclipse.org/bugs/show_bug.cgi?id=19253.
  467. * Since 3.4 we also don't log non-exists exception in non-working copies.
  468. */
  469. public static boolean isExceptionToBeLogged(CoreException exception) {
  470. if (!(exception instanceof JavaModelException))
  471. return true;
  472. JavaModelException je= (JavaModelException)exception;
  473. if (!je.isDoesNotExist())
  474. return true;
  475. return false;
  476. }
  477. public static IType[] getAllSuperTypes(IType type, IProgressMonitor pm) throws JavaModelException {
  478. try {
  479. // workaround for 23656
  480. IType[] superTypes= SuperTypeHierarchyCache.getTypeHierarchy(type).getAllSupertypes(type);
  481. if (type.isInterface()) {
  482. IType objekt= type.getJavaProject().findType("java.lang.Object");//$NON-NLS-1$
  483. if (objekt != null) {
  484. IType[] superInterfacesAndObject= new IType[superTypes.length + 1];
  485. System.arraycopy(superTypes, 0, superInterfacesAndObject, 0, superTypes.length);
  486. superInterfacesAndObject[superTypes.length]= objekt;
  487. return superInterfacesAndObject;
  488. }
  489. }
  490. return superTypes;
  491. } finally {
  492. if (pm != null)
  493. pm.done();
  494. }
  495. }
  496. public static boolean isSuperType(ITypeHierarchy hierarchy, IType possibleSuperType, IType type) {
  497. // filed bug 112635 to add this method to ITypeHierarchy
  498. IType superClass= hierarchy.getSuperclass(type);
  499. if (superClass != null && (possibleSuperType.equals(superClass) || isSuperType(hierarchy, possibleSuperType, superClass))) {
  500. return true;
  501. }
  502. if (Flags.isInterface(hierarchy.getCachedFlags(possibleSuperType))) {
  503. IType[] superInterfaces= hierarchy.getSuperInterfaces(type);
  504. for (int i= 0; i < superInterfaces.length; i++) {
  505. IType curr= superInterfaces[i];
  506. if (possibleSuperType.equals(curr) || isSuperType(hierarchy, possibleSuperType, curr)) {
  507. return true;
  508. }
  509. }
  510. }
  511. return false;
  512. }
  513. public static boolean isExcludedPath(IPath resourcePath, IPath[] exclusionPatterns) {
  514. char[] path = resourcePath.toString().toCharArray();
  515. for (int i = 0, length = exclusionPatterns.length; i < length; i++) {
  516. char[] pattern= exclusionPatterns[i].toString().toCharArray();
  517. if (CharOperation.pathMatch(pattern, path, true, '/')) {
  518. return true;
  519. }
  520. }
  521. return false;
  522. }
  523. /**
  524. * Returns whether the given resource path matches one of the exclusion
  525. * patterns.
  526. * @param resourcePath the resource path
  527. * @param exclusionPatterns the exclusion patterns
  528. * @return returns <code> true</code> if the given resource path matches one of the exclusion
  529. *
  530. * @see IClasspathEntry#getExclusionPatterns
  531. */
  532. public static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
  533. if (exclusionPatterns == null) return false;
  534. char[] path = resourcePath.toString().toCharArray();
  535. for (int i = 0, length = exclusionPatterns.length; i < length; i++)
  536. if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
  537. return true;
  538. return false;
  539. }
  540. /**
  541. * Force a reconcile of a compilation unit.
  542. * @param unit the compilation unit
  543. * @throws JavaModelException thrown when the compilation unit can not be accessed
  544. */
  545. public static void reconcile(ICompilationUnit unit) throws JavaModelException {
  546. unit.reconcile(
  547. ICompilationUnit.NO_AST,
  548. false /* don't force problem detection */,
  549. null /* use primary owner */,
  550. null /* no progress monitor */);
  551. }
  552. /**
  553. * Helper method that tests if an classpath entry can be found in a
  554. * container. <code>null</code> is returned if the entry can not be found
  555. * or if the container does not allows the configuration of source
  556. * attachments
  557. * @param jproject The container's parent project
  558. * @param containerPath The path of the container
  559. * @param libPath The path of the library to be found
  560. * @return IClasspathEntry A classpath entry from the container of
  561. * <code>null</code> if the container can not be modified.
  562. * @throws JavaModelException thrown if accessing the container failed
  563. */
  564. public static IClasspathEntry getClasspathEntryToEdit(IJavaProject jproject, IPath containerPath, IPath libPath) throws JavaModelException {
  565. IClasspathContainer container= JavaCore.getClasspathContainer(containerPath, jproject);
  566. ClasspathContainerInitializer initializer= JavaCore.getClasspathContainerInitializer(containerPath.segment(0));
  567. if (container != null && initializer != null && initializer.canUpdateClasspathContainer(containerPath, jproject)) {
  568. return findEntryInContainer(container, libPath);
  569. }
  570. return null; // attachment not possible
  571. }
  572. /**
  573. * Finds an entry in a container. <code>null</code> is returned if the entry can not be found
  574. * @param container The container
  575. * @param libPath The path of the library to be found
  576. * @return IClasspathEntry A classpath entry from the container of
  577. * <code>null</code> if the container can not be modified.
  578. */
  579. public static IClasspathEntry findEntryInContainer(IClasspathContainer container, IPath libPath) {
  580. IClasspathEntry[] entries= container.getClasspathEntries();
  581. for (int i= 0; i < entries.length; i++) {
  582. IClasspathEntry curr= entries[i];
  583. IClasspathEntry resolved= JavaCore.getResolvedClasspathEntry(curr);
  584. if (resolved != null && libPath.equals(resolved.getPath())) {
  585. return curr; // return the real entry
  586. }
  587. }
  588. return null; // attachment not possible
  589. }
  590. /**
  591. * Returns the classpath entry of the given package fragment root. This is the raw entry, except
  592. * if the root is a referenced library, in which case it's the resolved entry.
  593. *
  594. * @param root a package fragment root
  595. * @return the corresponding classpath entry
  596. * @throws JavaModelException if accessing the entry failed
  597. * @since 3.6
  598. */
  599. public static IClasspathEntry getClasspathEntry(IPackageFragmentRoot root) throws JavaModelException {
  600. IClasspathEntry rawEntry= root.getRawClasspathEntry();
  601. int rawEntryKind= rawEntry.getEntryKind();
  602. switch (rawEntryKind) {
  603. case IClasspathEntry.CPE_LIBRARY:
  604. case IClasspathEntry.CPE_VARIABLE:
  605. case IClasspathEntry.CPE_CONTAINER: // should not happen, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=305037
  606. if (root.isArchive() && root.getKind() == IPackageFragmentRoot.K_BINARY) {
  607. IClasspathEntry resolvedEntry= root.getResolvedClasspathEntry();
  608. if (resolvedEntry.getReferencingEntry() != null)
  609. return resolvedEntry;
  610. else
  611. return rawEntry;
  612. }
  613. }
  614. return rawEntry;
  615. }
  616. /**
  617. * Get all compilation units of a selection.
  618. *
  619. * @param javaElements the selected java elements
  620. * @return all compilation units containing and contained in elements from javaElements
  621. * @throws JavaModelException if this element does not exist or if an exception occurs while
  622. * accessing its corresponding resource
  623. */
  624. public static ICompilationUnit[] getAllCompilationUnits(IJavaElement[] javaElements) throws JavaModelException {
  625. HashSet<ICompilationUnit> result= new HashSet<ICompilationUnit>();
  626. for (int i= 0; i < javaElements.length; i++) {
  627. addAllCus(result, javaElements[i]);
  628. }
  629. return result.toArray(new ICompilationUnit[result.size()]);
  630. }
  631. private static void addAllCus(HashSet<ICompilationUnit> collector, IJavaElement javaElement) throws JavaModelException {
  632. switch (javaElement.getElementType()) {
  633. case IJavaElement.JAVA_PROJECT:
  634. IJavaProject javaProject= (IJavaProject) javaElement;
  635. IPackageFragmentRoot[] packageFragmentRoots= javaProject.getPackageFragmentRoots();
  636. for (int i= 0; i < packageFragmentRoots.length; i++)
  637. addAllCus(collector, packageFragmentRoots[i]);
  638. return;
  639. case IJavaElement.PACKAGE_FRAGMENT_ROOT:
  640. IPackageFragmentRoot packageFragmentRoot= (IPackageFragmentRoot) javaElement;
  641. if (packageFragmentRoot.getKind() != IPackageFragmentRoot.K_SOURCE)
  642. return;
  643. IJavaElement[] packageFragments= packageFragmentRoot.getChildren();
  644. for (int j= 0; j < packageFragments.length; j++)
  645. addAllCus(collector, packageFragments[j]);
  646. return;
  647. case IJavaElement.PACKAGE_FRAGMENT:
  648. IPackageFragment packageFragment= (IPackageFragment) javaElement;
  649. collector.addAll(Arrays.asList(packageFragment.getCompilationUnits()));
  650. return;
  651. case IJavaElement.COMPILATION_UNIT:
  652. collector.add((ICompilationUnit) javaElement);
  653. return;
  654. default:
  655. IJavaElement cu= javaElement.getAncestor(IJavaElement.COMPILATION_UNIT);
  656. if (cu != null)
  657. collector.add((ICompilationUnit) cu);
  658. }
  659. }
  660. public static void setComplianceOptions(Map<String, String> map, String compliance) {
  661. JavaCore.setComplianceOptions(compliance, map);
  662. }
  663. public static void setDefaultClassfileOptions(Map<String, String> map, String compliance) {
  664. map.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, is50OrHigher(compliance) ? JavaCore.ENABLED : JavaCore.DISABLED);
  665. map.put(JavaCore.COMPILER_LOCAL_VARIABLE_ATTR, JavaCore.GENERATE);
  666. map.put(JavaCore.COMPILER_LINE_NUMBER_ATTR, JavaCore.GENERATE);
  667. map.put(JavaCore.COMPILER_SOURCE_FILE_ATTR, JavaCore.GENERATE);
  668. map.put(JavaCore.COMPILER_CODEGEN_UNUSED_LOCAL, JavaCore.PRESERVE);
  669. }
  670. /**
  671. * @param version1 the first version
  672. * @param version2 the second version
  673. * @return <code>true</code> iff version1 is less than version2
  674. */
  675. public static boolean isVersionLessThan(String version1, String version2) {
  676. if (JavaCore.VERSION_CLDC_1_1.equals(version1)) {
  677. version1= JavaCore.VERSION_1_1 + 'a';
  678. }
  679. if (JavaCore.VERSION_CLDC_1_1.equals(version2)) {
  680. version2= JavaCore.VERSION_1_1 + 'a';
  681. }
  682. return version1.compareTo(version2) < 0;
  683. }
  684. public static boolean is50OrHigher(String compliance) {
  685. return !isVersionLessThan(compliance, JavaCore.VERSION_1_5);
  686. }
  687. public static boolean is17OrHigher(String compliance) {
  688. return !isVersionLessThan(compliance, JavaCore.VERSION_1_7);
  689. }
  690. /**
  691. * Checks if the given project or workspace has source compliance 1.5 or greater.
  692. *
  693. * @param project the project to test or <code>null</code> to test the workspace settings
  694. * @return <code>true</code> if the given project or workspace has source compliance 1.5 or greater.
  695. */
  696. public static boolean is50OrHigher(IJavaProject project) {
  697. String source= project != null ? project.getOption(JavaCore.COMPILER_SOURCE, true) : JavaCore.getOption(JavaCore.COMPILER_SOURCE);
  698. return is50OrHigher(source);
  699. }
  700. /**
  701. * Checks if the given project or workspace has source compliance 1.7 or greater.
  702. *
  703. * @param project the project to test or <code>null</code> to test the workspace settings
  704. * @return <code>true</code> if the given project or workspace has source compliance 1.7 or greater.
  705. */
  706. public static boolean is17OrHigher(IJavaProject project) {
  707. String source= project != null ? project.getOption(JavaCore.COMPILER_SOURCE, true) : JavaCore.getOption(JavaCore.COMPILER_SOURCE);
  708. return is17OrHigher(source);
  709. }
  710. /**
  711. * Checks if the JRE of the given project or workspace default JRE have source compliance 1.5 or
  712. * greater.
  713. *
  714. * @param project the project to test or <code>null</code> to test the workspace JRE
  715. * @return <code>true</code> if the JRE of the given project or workspace default JRE have
  716. * source compliance 1.5 or greater.
  717. * @throws CoreException if unable to determine the project's VM install
  718. */
  719. public static boolean is50OrHigherJRE(IJavaProject project) throws CoreException {
  720. IVMInstall vmInstall;
  721. if (project == null) {
  722. vmInstall= JavaRuntime.getDefaultVMInstall();
  723. } else {
  724. vmInstall= JavaRuntime.getVMInstall(project);
  725. }
  726. if (!(vmInstall instanceof IVMInstall2))
  727. return true; // assume 1.5.
  728. String compliance= getCompilerCompliance((IVMInstall2) vmInstall, null);
  729. if (compliance == null)
  730. return true; // assume 1.5
  731. return compliance.startsWith(JavaCore.VERSION_1_5)
  732. || compliance.startsWith(JavaCore.VERSION_1_6)
  733. || compliance.startsWith(JavaCore.VERSION_1_7);
  734. }
  735. public static String getCompilerCompliance(IVMInstall2 vMInstall, String defaultCompliance) {
  736. String version= vMInstall.getJavaVersion();
  737. if (version == null) {
  738. return defaultCompliance;
  739. } else if (version.startsWith(JavaCore.VERSION_1_7)) {
  740. return JavaCore.VERSION_1_7;
  741. } else if (version.startsWith(JavaCore.VERSION_1_6)) {
  742. return JavaCore.VERSION_1_6;
  743. } else if (version.startsWith(JavaCore.VERSION_1_5)) {
  744. return JavaCore.VERSION_1_5;
  745. } else if (version.startsWith(JavaCore.VERSION_1_4)) {
  746. return JavaCore.VERSION_1_4;
  747. } else if (version.startsWith(JavaCore.VERSION_1_3)) {
  748. return JavaCore.VERSION_1_3;
  749. } else if (version.startsWith(JavaCore.VERSION_1_2)) {
  750. return JavaCore.VERSION_1_3;
  751. } else if (version.startsWith(JavaCore.VERSION_1_1)) {
  752. return JavaCore.VERSION_1_3;
  753. }
  754. return defaultCompliance;
  755. }
  756. public static String getExecutionEnvironmentCompliance(IExecutionEnvironment executionEnvironment) {
  757. Map<String, String> complianceOptions= executionEnvironment.getComplianceOptions();
  758. if (complianceOptions != null) {
  759. Object compliance= complianceOptions.get(JavaCore.COMPILER_COMPLIANCE);
  760. if (compliance instanceof String)
  761. return (String)compliance;
  762. }
  763. // fallback:
  764. String desc= executionEnvironment.getId();
  765. if (desc.indexOf(JavaCore.VERSION_1_7) != -1) {
  766. return JavaCore.VERSION_1_7;
  767. } else if (desc.indexOf(JavaCore.VERSION_1_6) != -1) {
  768. return JavaCore.VERSION_1_6;
  769. } else if (desc.indexOf(JavaCore.VERSION_1_5) != -1) {
  770. return JavaCore.VERSION_1_5;
  771. } else if (desc.indexOf(JavaCore.VERSION_1_4) != -1) {
  772. return JavaCore.VERSION_1_4;
  773. }
  774. return JavaCore.VERSION_1_3;
  775. }
  776. /**
  777. * Compute a new name for a compilation unit, given the name of the new main type.
  778. * This query tries to maintain the existing extension (e.g. ".java").
  779. *
  780. * @param cu a compilation unit
  781. * @param newMainName the new name of the cu's main type (without extension)
  782. * @return the new name for the compilation unit
  783. */
  784. public static String getRenamedCUName(ICompilationUnit cu, String newMainName) {
  785. String oldName = cu.getElementName();
  786. int i = oldName.lastIndexOf('.');
  787. if (i != -1) {
  788. return newMainName + oldName.substring(i);
  789. } else {
  790. return newMainName;
  791. }
  792. }
  793. /**
  794. * Applies an text edit to a compilation unit. Filed bug 117694 against jdt.core.
  795. * @param cu the compilation unit to apply the edit to
  796. * @param edit the edit to apply
  797. * @param save is set, save the CU after the edit has been applied
  798. * @param monitor the progress monitor to use
  799. * @throws CoreException Thrown when the access to the CU failed
  800. * @throws ValidateEditException if validate edit fails
  801. */
  802. public static void applyEdit(ICompilationUnit cu, TextEdit edit, boolean save, IProgressMonitor monitor) throws CoreException, ValidateEditException {
  803. IFile file= (IFile) cu.getResource();
  804. if (!save || !file.exists()) {
  805. cu.applyTextEdit(edit, monitor);
  806. } else {
  807. if (monitor == null) {
  808. monitor= new NullProgressMonitor();
  809. }
  810. monitor.beginTask(CorextMessages.JavaModelUtil_applyedit_operation, 2);
  811. try {
  812. IStatus status= Resources.makeCommittable(file, null);
  813. if (!status.isOK()) {
  814. throw new ValidateEditException(status);
  815. }
  816. cu.applyTextEdit(edit, new SubProgressMonitor(monitor, 1));
  817. cu.save(new SubProgressMonitor(monitor, 1), true);
  818. } finally {
  819. monitor.done();
  820. }
  821. }
  822. }
  823. public static boolean isImplicitImport(String qualifier, ICompilationUnit cu) {
  824. if ("java.lang".equals(qualifier)) { //$NON-NLS-1$
  825. return true;
  826. }
  827. String packageName= cu.getParent().getElementName();
  828. if (qualifier.equals(packageName)) {
  829. return true;
  830. }
  831. String typeName= JavaCore.removeJavaLikeExtension(cu.getElementName());
  832. String mainTypeName= JavaModelUtil.concatenateName(packageName, typeName);
  833. return qualifier.equals(mainTypeName);
  834. }
  835. public static boolean isOpenableStorage(Object storage) {
  836. if (storage instanceof IJarEntryResource) {
  837. return ((IJarEntryResource) storage).isFile();
  838. } else {
  839. return storage instanceof IStorage;
  840. }
  841. }
  842. /**
  843. * Tells whether the given CU is the package-info.java.
  844. *
  845. * @param cu the compilation unit to test
  846. * @return <code>true</code> if the given CU is the package-info.java
  847. * @since 3.4
  848. */
  849. public static boolean isPackageInfo(ICompilationUnit cu) {
  850. return PACKAGE_INFO_JAVA.equals(cu.getElementName());
  851. }
  852. public static boolean isPolymorphicSignature(IMethod method) {
  853. return method.getAnnotation("java.lang.invoke.MethodHandle$PolymorphicSignature").exists(); //$NON-NLS-1$
  854. }
  855. }