PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/plugin-java/che-plugin-java-ext-jdt/org-eclipse-jdt-ui/src/main/java/org/eclipse/jdt/internal/ui/javaeditor/ASTProvider.java

https://gitlab.com/unofficial-mirrors/eclipse-che
Java | 288 lines | 145 code | 33 blank | 110 comment | 54 complexity | 3b4c7f22412c76c87acc7cd4a577941b MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2013 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. *******************************************************************************/
  11. package org.eclipse.jdt.internal.ui.javaeditor;
  12. import org.eclipse.che.jdt.dom.ASTNodes;
  13. import org.eclipse.core.runtime.IProgressMonitor;
  14. import org.eclipse.core.runtime.ISafeRunnable;
  15. import org.eclipse.core.runtime.OperationCanceledException;
  16. import org.eclipse.core.runtime.SafeRunner;
  17. import org.eclipse.jdt.core.ITypeRoot;
  18. import org.eclipse.jdt.core.JavaModelException;
  19. import org.eclipse.jdt.core.dom.AST;
  20. import org.eclipse.jdt.core.dom.ASTNode;
  21. import org.eclipse.jdt.core.dom.CheASTParser;
  22. import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
  23. import org.eclipse.jdt.core.dom.CompilationUnit;
  24. import org.eclipse.jdt.ui.SharedASTProvider;
  25. import org.slf4j.Logger;
  26. import org.slf4j.LoggerFactory;
  27. import java.util.List;
  28. /**
  29. * @author Evgen Vidolob
  30. */
  31. public class ASTProvider {
  32. public static final int SHARED_AST_LEVEL = AST.JLS8;
  33. public static final boolean SHARED_AST_STATEMENT_RECOVERY = true;
  34. public static final boolean SHARED_BINDING_RECOVERY = true;
  35. private static final Logger LOG = LoggerFactory.getLogger(ASTProvider.class);
  36. private static final String DEBUG_PREFIX = "ASTProvider > "; //$NON-NLS-1$
  37. private Object fReconcileLock= new Object();
  38. private CompilationUnit fAST;
  39. /**
  40. * Tells whether this class is in debug mode.
  41. * @since 3.0
  42. */
  43. private static final boolean DEBUG = false;
  44. /**
  45. * Checks whether the given Java element has accessible source.
  46. *
  47. * @param je the Java element to test
  48. * @return <code>true</code> if the element has source
  49. * @since 3.2
  50. */
  51. private static boolean hasSource(ITypeRoot je) {
  52. if (je == null || !je.exists())
  53. return false;
  54. try {
  55. return je.getBuffer() != null;
  56. } catch (JavaModelException ex) {
  57. LOG.error(ex.getMessage(), ex);
  58. }
  59. return false;
  60. }
  61. /**
  62. * Returns a string for the given Java element used for debugging.
  63. *
  64. * @param javaElement the compilation unit AST
  65. * @return a string used for debugging
  66. */
  67. private String toString(ITypeRoot javaElement) {
  68. if (javaElement == null)
  69. return "null"; //$NON-NLS-1$
  70. else
  71. return javaElement.getElementName();
  72. }
  73. /**
  74. * Returns a string for the given AST used for debugging.
  75. *
  76. * @param ast the compilation unit AST
  77. * @return a string used for debugging
  78. */
  79. private String toString(CompilationUnit ast) {
  80. if (ast == null)
  81. return "null"; //$NON-NLS-1$
  82. List<AbstractTypeDeclaration> types= ast.types();
  83. if (types != null && types.size() > 0)
  84. return types.get(0).getName().getIdentifier() + "(" + ast.hashCode() + ")"; //$NON-NLS-1$//$NON-NLS-2$
  85. else
  86. return "AST without any type"; //$NON-NLS-1$
  87. }
  88. /**
  89. * Creates a new compilation unit AST.
  90. *
  91. * @param input the Java element for which to create the AST
  92. * @param progressMonitor the progress monitor
  93. * @return AST
  94. */
  95. public static CompilationUnit createAST(final ITypeRoot input, final IProgressMonitor progressMonitor) {
  96. if (!hasSource(input))
  97. return null;
  98. if (progressMonitor != null && progressMonitor.isCanceled())
  99. return null;
  100. final CheASTParser parser = CheASTParser.newParser(SHARED_AST_LEVEL);
  101. parser.setResolveBindings(true);
  102. parser.setStatementsRecovery(SHARED_AST_STATEMENT_RECOVERY);
  103. parser.setBindingsRecovery(SHARED_BINDING_RECOVERY);
  104. parser.setSource(input);
  105. if (progressMonitor != null && progressMonitor.isCanceled())
  106. return null;
  107. final CompilationUnit root[]= new CompilationUnit[1];
  108. SafeRunner.run(new ISafeRunnable() {
  109. public void run() {
  110. try {
  111. if (progressMonitor != null && progressMonitor.isCanceled())
  112. return;
  113. if (DEBUG)
  114. System.err.println(getThreadName() + " - " + DEBUG_PREFIX + "creating AST for: " +
  115. input.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
  116. root[0] = (CompilationUnit)parser.createAST(progressMonitor);
  117. //mark as unmodifiable
  118. ASTNodes.setFlagsToAST(root[0], ASTNode.PROTECT);
  119. } catch (OperationCanceledException ex) {
  120. return;
  121. }
  122. }
  123. public void handleException(Throwable ex) {
  124. LOG.error(ex.getMessage(), ex);
  125. }
  126. });
  127. return root[0];
  128. }
  129. private static String getThreadName() {
  130. String name= Thread.currentThread().getName();
  131. if (name != null)
  132. return name;
  133. else
  134. return Thread.currentThread().toString();
  135. }
  136. /**
  137. * Returns a shared compilation unit AST for the given Java element.
  138. * <p>
  139. * Clients are not allowed to modify the AST and must synchronize all access to its nodes.
  140. * </p>
  141. *
  142. * @param input the Java element, must not be <code>null</code>
  143. * @param waitFlag {@link SharedASTProvider#WAIT_YES}, {@link SharedASTProvider#WAIT_NO} or
  144. * {@link SharedASTProvider#WAIT_ACTIVE_ONLY}
  145. * @param progressMonitor the progress monitor or <code>null</code>
  146. * @return the AST or <code>null</code> if the AST is not available
  147. */
  148. public CompilationUnit getAST(final ITypeRoot input, SharedASTProvider.WAIT_FLAG waitFlag, IProgressMonitor progressMonitor) {
  149. if (input == null || waitFlag == null)
  150. throw new IllegalArgumentException("input or wait flag are null"); //$NON-NLS-1$
  151. if (progressMonitor != null && progressMonitor.isCanceled())
  152. return null;
  153. boolean isActiveElement;
  154. synchronized (this) {
  155. isActiveElement= false; //input.equals(fActiveJavaElement);
  156. if (isActiveElement) {
  157. if (fAST != null) {
  158. if (DEBUG)
  159. System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "returning cached AST:" + toString(fAST) + " for: " + input.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  160. return fAST;
  161. }
  162. if (waitFlag == SharedASTProvider.WAIT_NO) {
  163. if (DEBUG)
  164. System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "returning null (WAIT_NO) for: " + input.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
  165. return null;
  166. }
  167. }
  168. }
  169. final boolean canReturnNull= waitFlag == SharedASTProvider.WAIT_NO || (waitFlag == SharedASTProvider.WAIT_ACTIVE_ONLY && !(isActiveElement && fAST == null));
  170. boolean isReconciling= false;
  171. final ITypeRoot activeElement;
  172. if (isActiveElement) {
  173. // synchronized (fReconcileLock) {
  174. // activeElement= fReconcilingJavaElement;
  175. // isReconciling= isReconciling(input);
  176. // if (!isReconciling && !canReturnNull)
  177. // aboutToBeReconciled(input);
  178. // }
  179. } else
  180. activeElement= null;
  181. if (isReconciling) {
  182. // Wait for AST
  183. // synchronized (fWaitLock) {
  184. // if (isReconciling(input)) {
  185. // if (DEBUG)
  186. // System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "waiting for AST for: " + input.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
  187. // fWaitLock.wait(30000); // XXX: The 30 seconds timeout is an attempt to at least avoid a deadlock. See https://bugs.eclipse.org/366048#c21
  188. // }
  189. // }
  190. // Check whether active element is still valid
  191. // synchronized (this) {
  192. // if (activeElement == fActiveJavaElement && fAST != null) {
  193. // if (DEBUG)
  194. // System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "...got AST: " + toString(fAST) + " for: " + input.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  195. //
  196. // return fAST;
  197. // }
  198. // }
  199. return getAST(input, waitFlag, progressMonitor);
  200. } /*else if (canReturnNull)
  201. return null;*/
  202. CompilationUnit ast= null;
  203. try {
  204. ast= createAST(input, progressMonitor);
  205. if (progressMonitor != null && progressMonitor.isCanceled()) {
  206. ast= null;
  207. if (DEBUG)
  208. System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "Ignore created AST for: " + input.getElementName() + " - operation has been cancelled"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  209. }
  210. } finally {
  211. if (isActiveElement) {
  212. if (fAST != null) {
  213. // in the meantime, reconcile created a new AST. Return that one
  214. if (DEBUG)
  215. System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "Ignore created AST for " + input.getElementName() + " - AST from reconciler is newer"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  216. reconciled(fAST, input, null);
  217. return fAST;
  218. } else
  219. reconciled(ast, input, null);
  220. }
  221. }
  222. return ast;
  223. }
  224. /**
  225. * Update internal structures after reconcile.
  226. *
  227. * @param ast the compilation unit AST or <code>null</code> if the working copy was consistent
  228. * or reconciliation has been cancelled
  229. * @param javaElement the Java element for which the AST was built
  230. * @param progressMonitor the progress monitor
  231. * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit,
  232. * boolean, IProgressMonitor)
  233. */
  234. void reconciled(CompilationUnit ast, ITypeRoot javaElement, IProgressMonitor progressMonitor) {
  235. // if (DEBUG)
  236. // System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "reconciled: " + toString(javaElement) + ", AST: " + toString(ast)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  237. //
  238. // synchronized (fReconcileLock) {
  239. // fIsReconciling= false;
  240. // if (javaElement == null || !javaElement.equals(fReconcilingJavaElement)) {
  241. //
  242. // if (DEBUG)
  243. // System.out.println(getThreadName() + " - " + DEBUG_PREFIX + " ignoring AST of out-dated editor"); //$NON-NLS-1$ //$NON-NLS-2$
  244. //
  245. // // Signal - threads might wait for wrong element
  246. // synchronized (fWaitLock) {
  247. // fWaitLock.notifyAll();
  248. // }
  249. //
  250. // return;
  251. // }
  252. // cache(ast, javaElement);
  253. // }
  254. }
  255. }