1 /*******************************************************************************
2 * Copyright (c) 2000, 2017 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 * IBM Corporation - initial API and implementation
13 * Alex Smirnoff (alexsmr@sympatico.ca) - part of the changes to support Java-like extension
14 * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=71460)
15 *******************************************************************************/
16 package org.eclipse.jdt.internal.core;
17
18 import java.io.IOException;
19 import java.util.*;
20
21 import org.eclipse.core.resources.*;
22 import org.eclipse.core.runtime.*;
23 import org.eclipse.jdt.core.*;
24 import org.eclipse.jdt.core.compiler.*;
25 import org.eclipse.jdt.core.dom.AST;
26 import org.eclipse.jdt.internal.compiler.IProblemFactory;
27 import org.eclipse.jdt.internal.compiler.SourceElementParser;
28 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
29 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
30 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
31 import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
32 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
33 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
34 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
35 import org.eclipse.jdt.internal.core.util.Messages;
36 import org.eclipse.jdt.internal.core.util.Util;
37 import org.eclipse.jface.text.BadLocationException;
38 import org.eclipse.jface.text.IDocument;
39 import org.eclipse.text.edits.MalformedTreeException;
40 import org.eclipse.text.edits.TextEdit;
41 import org.eclipse.text.edits.UndoEdit;
42
43 /**
44 * @see ICompilationUnit
45 */
46 @SuppressWarnings({"rawtypes", "unchecked"})
47 public class CompilationUnit extends Openable implements ICompilationUnit, org.eclipse.jdt.internal.compiler.env.ICompilationUnit, SuffixConstants {
48 /**
49 * Internal synonym for deprecated constant AST.JSL2
50 * to alleviate deprecation warnings.
51 * @deprecated
52 */
53 /*package*/ static final int JLS2_INTERNAL = AST.JLS2;
54
55 private static final IImportDeclaration[] NO_IMPORTS = new IImportDeclaration[0];
56
57 protected String name;
58 public WorkingCopyOwner owner;
59
60 /**
61 * Constructs a handle to a compilation unit with the given name in the
62 * specified package for the specified owner
63 */
CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner)64 public CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
65 super(parent);
66 this.name = name;
67 this.owner = owner;
68 }
69
70
71 @Override
applyTextEdit(TextEdit edit, IProgressMonitor monitor)72 public UndoEdit applyTextEdit(TextEdit edit, IProgressMonitor monitor) throws JavaModelException {
73 IBuffer buffer = getBuffer();
74 if (buffer instanceof IBuffer.ITextEditCapability) {
75 return ((IBuffer.ITextEditCapability) buffer).applyTextEdit(edit, monitor);
76 } else if (buffer != null) {
77 IDocument document = buffer instanceof IDocument ? (IDocument) buffer : new DocumentAdapter(buffer);
78 try {
79 UndoEdit undoEdit= edit.apply(document);
80 return undoEdit;
81 } catch (MalformedTreeException | BadLocationException e) {
82 throw new JavaModelException(e, IJavaModelStatusConstants.BAD_TEXT_EDIT_LOCATION);
83 }
84 }
85 return null; // can not happen, there are no compilation units without buffer
86 }
87
88 @Override
becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor)89 public void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
90 JavaModelManager manager = JavaModelManager.getJavaModelManager();
91 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(this, false/*don't create*/, true /*record usage*/, null/*no problem requestor needed*/);
92 if (perWorkingCopyInfo == null) {
93 // close cu and its children
94 close();
95
96 BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(this, problemRequestor);
97 operation.runOperation(monitor);
98 }
99 }
100
101 @Override
becomeWorkingCopy(IProgressMonitor monitor)102 public void becomeWorkingCopy(IProgressMonitor monitor) throws JavaModelException {
103 IProblemRequestor requestor = this.owner == null ? null : this.owner.getProblemRequestor(this);
104 becomeWorkingCopy(requestor, monitor);
105 }
106 @Override
buildStructure(OpenableElementInfo info, final IProgressMonitor pm, Map newElements, IResource underlyingResource)107 protected boolean buildStructure(OpenableElementInfo info, final IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
108 CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
109
110 // ensure buffer is opened
111 IBuffer buffer = getBufferManager().getBuffer(CompilationUnit.this);
112 if (buffer == null) {
113 openBuffer(pm, unitInfo); // open buffer independently from the info, since we are building the info
114 }
115
116 // generate structure and compute syntax problems if needed
117 CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
118 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = getPerWorkingCopyInfo();
119 IJavaProject project = getJavaProject();
120
121 boolean createAST;
122 boolean resolveBindings;
123 int reconcileFlags;
124 HashMap problems;
125 if (info instanceof ASTHolderCUInfo) {
126 ASTHolderCUInfo astHolder = (ASTHolderCUInfo) info;
127 createAST = astHolder.astLevel != NO_AST;
128 resolveBindings = astHolder.resolveBindings;
129 reconcileFlags = astHolder.reconcileFlags;
130 problems = astHolder.problems;
131 } else {
132 createAST = false;
133 resolveBindings = false;
134 reconcileFlags = 0;
135 problems = null;
136 }
137
138 boolean computeProblems = perWorkingCopyInfo != null && perWorkingCopyInfo.isActive() && project != null && JavaProject.hasJavaNature(project.getProject());
139 IProblemFactory problemFactory = new DefaultProblemFactory();
140 Map options = project == null ? JavaCore.getOptions() : project.getOptions(true);
141 if (!computeProblems) {
142 // disable task tags checking to speed up parsing
143 options.put(JavaCore.COMPILER_TASK_TAGS, ""); //$NON-NLS-1$
144 }
145 CompilerOptions compilerOptions = new CompilerOptions(options);
146 compilerOptions.ignoreMethodBodies = (reconcileFlags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
147 SourceElementParser parser = new SourceElementParser(
148 requestor,
149 problemFactory,
150 compilerOptions,
151 true/*report local declarations*/,
152 !createAST /*optimize string literals only if not creating a DOM AST*/);
153 parser.reportOnlyOneSyntaxError = !computeProblems;
154 parser.setMethodsFullRecovery(true);
155 parser.setStatementsRecovery((reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
156
157 if (!computeProblems && !resolveBindings && !createAST) // disable javadoc parsing if not computing problems, not resolving and not creating ast
158 parser.javadocParser.checkDocComment = false;
159 requestor.parser = parser;
160
161 // update timestamp (might be IResource.NULL_STAMP if original does not exist)
162 if (underlyingResource == null) {
163 underlyingResource = getResource();
164 }
165 // underlying resource is null in the case of a working copy on a class file in a jar
166 if (underlyingResource != null)
167 unitInfo.timestamp = ((IFile)underlyingResource).getModificationStamp();
168
169 // compute other problems if needed
170 CompilationUnitDeclaration compilationUnitDeclaration = null;
171 CompilationUnit source = cloneCachingContents();
172 try {
173 if (computeProblems) {
174 if (problems == null) {
175 // report problems to the problem requestor
176 problems = new HashMap();
177 compilationUnitDeclaration = CompilationUnitProblemFinder.process(source, parser, this.owner, problems, createAST, reconcileFlags, pm);
178 try {
179 perWorkingCopyInfo.beginReporting();
180 for (Iterator iteraror = problems.values().iterator(); iteraror.hasNext();) {
181 CategorizedProblem[] categorizedProblems = (CategorizedProblem[]) iteraror.next();
182 if (categorizedProblems == null) continue;
183 for (int i = 0, length = categorizedProblems.length; i < length; i++) {
184 perWorkingCopyInfo.acceptProblem(categorizedProblems[i]);
185 }
186 }
187 } finally {
188 perWorkingCopyInfo.endReporting();
189 }
190 } else {
191 // collect problems
192 compilationUnitDeclaration = CompilationUnitProblemFinder.process(source, parser, this.owner, problems, createAST, reconcileFlags, pm);
193 }
194 } else {
195 compilationUnitDeclaration = parser.parseCompilationUnit(source, true /*full parse to find local elements*/, pm);
196 }
197
198 if (createAST) {
199 int astLevel = ((ASTHolderCUInfo) info).astLevel;
200 org.eclipse.jdt.core.dom.CompilationUnit cu = AST.convertCompilationUnit(astLevel, compilationUnitDeclaration, options, computeProblems, source, reconcileFlags, pm);
201 ((ASTHolderCUInfo) info).ast = cu;
202 }
203 } finally {
204 if (compilationUnitDeclaration != null) {
205 unitInfo.hasFunctionalTypes = compilationUnitDeclaration.hasFunctionalTypes();
206 compilationUnitDeclaration.cleanUp();
207 }
208 }
209
210 return unitInfo.isStructureKnown();
211 }
212 /*
213 * Clone this handle so that it caches its contents in memory.
214 * DO NOT PASS TO CLIENTS
215 */
cloneCachingContents()216 public CompilationUnit cloneCachingContents() {
217 return new CompilationUnit((PackageFragment) this.parent, this.name, this.owner) {
218 private char[] cachedContents;
219 @Override
220 public char[] getContents() {
221 if (this.cachedContents == null)
222 this.cachedContents = CompilationUnit.this.getContents();
223 return this.cachedContents;
224 }
225 @Override
226 public CompilationUnit originalFromClone() {
227 return CompilationUnit.this;
228 }
229 };
230 }
231
232 @Override
canBeRemovedFromCache()233 public boolean canBeRemovedFromCache() {
234 if (getPerWorkingCopyInfo() != null) return false; // working copies should remain in the cache until they are destroyed
235 return super.canBeRemovedFromCache();
236 }
237
238 @Override
canBufferBeRemovedFromCache(IBuffer buffer)239 public boolean canBufferBeRemovedFromCache(IBuffer buffer) {
240 if (getPerWorkingCopyInfo() != null) return false; // working copy buffers should remain in the cache until working copy is destroyed
241 return super.canBufferBeRemovedFromCache(buffer);
242 }
243
244 @Override
close()245 public void close() throws JavaModelException {
246 if (getPerWorkingCopyInfo() != null) return; // a working copy must remain opened until it is discarded
247 super.close();
248 }
249
250 @Override
closing(Object info)251 protected void closing(Object info) {
252 if (getPerWorkingCopyInfo() == null) {
253 super.closing(info);
254 } // else the buffer of a working copy must remain open for the lifetime of the working copy
255 }
256 /**
257 * @see ICodeAssist#codeComplete(int, ICompletionRequestor)
258 * @deprecated
259 */
260 @Override
codeComplete(int offset, ICompletionRequestor requestor)261 public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException {
262 codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
263 }
264 /**
265 * @see ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
266 * @deprecated
267 */
268 @Override
codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner workingCopyOwner)269 public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner workingCopyOwner) throws JavaModelException {
270 if (requestor == null) {
271 throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
272 }
273 codeComplete(offset, new org.eclipse.jdt.internal.codeassist.CompletionRequestorWrapper(requestor), workingCopyOwner);
274 }
275 /**
276 * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
277 * @deprecated - use codeComplete(int, ICompletionRequestor)
278 */
279 @Override
codeComplete(int offset, final ICodeCompletionRequestor requestor)280 public void codeComplete(int offset, final ICodeCompletionRequestor requestor) throws JavaModelException {
281
282 if (requestor == null){
283 codeComplete(offset, (ICompletionRequestor)null);
284 return;
285 }
286 codeComplete(
287 offset,
288 new ICompletionRequestor(){
289 @Override
290 public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
291 // ignore
292 }
293 @Override
294 public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
295 requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
296 }
297 @Override
298 public void acceptError(IProblem error) {
299 // was disabled in 1.0
300 }
301 @Override
302 public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
303 requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
304 }
305 @Override
306 public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
307 requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
308 }
309 @Override
310 public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
311 requestor.acceptKeyword(keywordName, completionStart, completionEnd);
312 }
313 @Override
314 public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
315 requestor.acceptLabel(labelName, completionStart, completionEnd);
316 }
317 @Override
318 public void acceptLocalVariable(char[] localVarName,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
319 // ignore
320 }
321 @Override
322 public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
323 // skip parameter names
324 requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
325 }
326 @Override
327 public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
328 // ignore
329 }
330 @Override
331 public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
332 requestor.acceptModifier(modifierName, completionStart, completionEnd);
333 }
334 @Override
335 public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
336 requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
337 }
338 @Override
339 public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
340 requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
341 }
342 @Override
343 public void acceptVariableName(char[] typePackageName,char[] typeName,char[] varName,char[] completionName,int completionStart,int completionEnd, int relevance){
344 // ignore
345 }
346 });
347 }
348
349 @Override
codeComplete(int offset, CompletionRequestor requestor)350 public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException {
351 codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
352 }
353
354 @Override
codeComplete(int offset, CompletionRequestor requestor, IProgressMonitor monitor)355 public void codeComplete(int offset, CompletionRequestor requestor, IProgressMonitor monitor) throws JavaModelException {
356 codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY, monitor);
357 }
358
359 @Override
codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner)360 public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner) throws JavaModelException {
361 codeComplete(offset, requestor, workingCopyOwner, null);
362 }
363
364 @Override
codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor)365 public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor) throws JavaModelException {
366 codeComplete(
367 this,
368 isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this,
369 offset,
370 requestor,
371 workingCopyOwner,
372 this,
373 monitor);
374 }
375
376 /**
377 * @see ICodeAssist#codeSelect(int, int)
378 */
379 @Override
codeSelect(int offset, int length)380 public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException {
381 return codeSelect(offset, length, DefaultWorkingCopyOwner.PRIMARY);
382 }
383 /**
384 * @see ICodeAssist#codeSelect(int, int, WorkingCopyOwner)
385 */
386 @Override
codeSelect(int offset, int length, WorkingCopyOwner workingCopyOwner)387 public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner workingCopyOwner) throws JavaModelException {
388 return super.codeSelect(this, offset, length, workingCopyOwner);
389 }
390 /**
391 * @see IWorkingCopy#commit(boolean, IProgressMonitor)
392 * @deprecated
393 */
394 @Override
commit(boolean force, IProgressMonitor monitor)395 public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
396 commitWorkingCopy(force, monitor);
397 }
398 /**
399 * @see ICompilationUnit#commitWorkingCopy(boolean, IProgressMonitor)
400 */
401 @Override
commitWorkingCopy(boolean force, IProgressMonitor monitor)402 public void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException {
403 CommitWorkingCopyOperation op= new CommitWorkingCopyOperation(this, force);
404 op.runOperation(monitor);
405 }
406 /**
407 * @see ISourceManipulation#copy(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
408 */
409 @Override
copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor)410 public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
411 if (container == null) {
412 throw new IllegalArgumentException(Messages.operation_nullContainer);
413 }
414 IJavaElement[] elements = new IJavaElement[] {this};
415 IJavaElement[] containers = new IJavaElement[] {container};
416 String[] renamings = null;
417 if (rename != null) {
418 renamings = new String[] {rename};
419 }
420 getJavaModel().copy(elements, containers, null, renamings, force, monitor);
421 }
422 /**
423 * Returns a new element info for this element.
424 */
425 @Override
createElementInfo()426 protected Object createElementInfo() {
427 return new CompilationUnitElementInfo();
428 }
429 /**
430 * @see ICompilationUnit#createImport(String, IJavaElement, IProgressMonitor)
431 */
432 @Override
createImport(String importName, IJavaElement sibling, IProgressMonitor monitor)433 public IImportDeclaration createImport(String importName, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException {
434 return createImport(importName, sibling, Flags.AccDefault, monitor);
435 }
436
437 /**
438 * @see ICompilationUnit#createImport(String, IJavaElement, int, IProgressMonitor)
439 * @since 3.0
440 */
441 @Override
createImport(String importName, IJavaElement sibling, int flags, IProgressMonitor monitor)442 public IImportDeclaration createImport(String importName, IJavaElement sibling, int flags, IProgressMonitor monitor) throws JavaModelException {
443 CreateImportOperation op = new CreateImportOperation(importName, this, flags);
444 if (sibling != null) {
445 op.createBefore(sibling);
446 }
447 op.runOperation(monitor);
448 return getImport(importName);
449 }
450
451 /**
452 * @see ICompilationUnit#createPackageDeclaration(String, IProgressMonitor)
453 */
454 @Override
createPackageDeclaration(String pkg, IProgressMonitor monitor)455 public IPackageDeclaration createPackageDeclaration(String pkg, IProgressMonitor monitor) throws JavaModelException {
456
457 CreatePackageDeclarationOperation op= new CreatePackageDeclarationOperation(pkg, this);
458 op.runOperation(monitor);
459 return getPackageDeclaration(pkg);
460 }
461 /**
462 * @see ICompilationUnit#createType(String, IJavaElement, boolean, IProgressMonitor)
463 */
464 @Override
createType(String content, IJavaElement sibling, boolean force, IProgressMonitor monitor)465 public IType createType(String content, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
466 if (!exists()) {
467 //autogenerate this compilation unit
468 IPackageFragment pkg = (IPackageFragment) getParent();
469 String source = ""; //$NON-NLS-1$
470 if (!pkg.isDefaultPackage()) {
471 //not the default package...add the package declaration
472 String lineSeparator = Util.getLineSeparator(null/*no existing source*/, getJavaProject());
473 source = "package " + pkg.getElementName() + ";" + lineSeparator + lineSeparator; //$NON-NLS-1$ //$NON-NLS-2$
474 }
475 CreateCompilationUnitOperation op = new CreateCompilationUnitOperation(pkg, this.name, source, force);
476 op.runOperation(monitor);
477 }
478 CreateTypeOperation op = new CreateTypeOperation(this, content, force);
479 if (sibling != null) {
480 op.createBefore(sibling);
481 }
482 op.runOperation(monitor);
483 return (IType) op.getResultElements()[0];
484 }
485 /**
486 * @see ISourceManipulation#delete(boolean, IProgressMonitor)
487 */
488 @Override
delete(boolean force, IProgressMonitor monitor)489 public void delete(boolean force, IProgressMonitor monitor) throws JavaModelException {
490 IJavaElement[] elements= new IJavaElement[] {this};
491 getJavaModel().delete(elements, force, monitor);
492 }
493 /**
494 * @see IWorkingCopy#destroy()
495 * @deprecated
496 */
497 @Override
destroy()498 public void destroy() {
499 try {
500 discardWorkingCopy();
501 } catch (JavaModelException e) {
502 if (JavaModelManager.VERBOSE)
503 e.printStackTrace();
504 }
505 }
506
507 @Override
discardWorkingCopy()508 public void discardWorkingCopy() throws JavaModelException {
509 // discard working copy and its children
510 DiscardWorkingCopyOperation op = new DiscardWorkingCopyOperation(this);
511 op.runOperation(null);
512 }
513 /**
514 * Returns true if this handle represents the same Java element
515 * as the given handle.
516 *
517 * @see Object#equals(java.lang.Object)
518 */
519 @Override
equals(Object obj)520 public boolean equals(Object obj) {
521 if (!(obj instanceof CompilationUnit)) return false;
522 CompilationUnit other = (CompilationUnit)obj;
523 return this.owner.equals(other.owner) && super.equals(obj);
524 }
525 /**
526 * @see ICompilationUnit#findElements(IJavaElement)
527 */
528 @Override
findElements(IJavaElement element)529 public IJavaElement[] findElements(IJavaElement element) {
530 if (element instanceof IType && ((IType) element).isLambda()) {
531 return null;
532 }
533 ArrayList children = new ArrayList();
534 while (element != null && element.getElementType() != IJavaElement.COMPILATION_UNIT) {
535 children.add(element);
536 element = element.getParent();
537 }
538 if (element == null) return null;
539 IJavaElement currentElement = this;
540 for (int i = children.size()-1; i >= 0; i--) {
541 SourceRefElement child = (SourceRefElement)children.get(i);
542 switch (child.getElementType()) {
543 case IJavaElement.PACKAGE_DECLARATION:
544 currentElement = ((ICompilationUnit)currentElement).getPackageDeclaration(child.getElementName());
545 break;
546 case IJavaElement.IMPORT_CONTAINER:
547 currentElement = ((ICompilationUnit)currentElement).getImportContainer();
548 break;
549 case IJavaElement.IMPORT_DECLARATION:
550 currentElement = ((IImportContainer)currentElement).getImport(child.getElementName());
551 break;
552 case IJavaElement.TYPE:
553 switch (currentElement.getElementType()) {
554 case IJavaElement.COMPILATION_UNIT:
555 currentElement = ((ICompilationUnit)currentElement).getType(child.getElementName());
556 break;
557 case IJavaElement.TYPE:
558 currentElement = ((IType)currentElement).getType(child.getElementName());
559 break;
560 case IJavaElement.FIELD:
561 case IJavaElement.INITIALIZER:
562 case IJavaElement.METHOD:
563 currentElement = ((IMember)currentElement).getType(child.getElementName(), child.occurrenceCount);
564 break;
565 }
566 break;
567 case IJavaElement.INITIALIZER:
568 currentElement = ((IType)currentElement).getInitializer(child.occurrenceCount);
569 break;
570 case IJavaElement.FIELD:
571 currentElement = ((IType)currentElement).getField(child.getElementName());
572 break;
573 case IJavaElement.METHOD:
574 currentElement = ((IType)currentElement).getMethod(child.getElementName(), ((IMethod)child).getParameterTypes());
575 break;
576 }
577
578 }
579 if (currentElement != null && currentElement.exists()) {
580 return new IJavaElement[] {currentElement};
581 } else {
582 return null;
583 }
584 }
585 /**
586 * @see ICompilationUnit#findPrimaryType()
587 */
588 @Override
findPrimaryType()589 public IType findPrimaryType() {
590 String typeName = Util.getNameWithoutJavaLikeExtension(getElementName());
591 IType primaryType= getType(typeName);
592 if (primaryType.exists()) {
593 return primaryType;
594 }
595 return null;
596 }
597
598 /**
599 * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory)
600 * @deprecated
601 */
602 @Override
findSharedWorkingCopy(IBufferFactory factory)603 public IJavaElement findSharedWorkingCopy(IBufferFactory factory) {
604
605 // if factory is null, default factory must be used
606 if (factory == null) factory = getBufferManager().getDefaultBufferFactory();
607
608 return findWorkingCopy(BufferFactoryWrapper.create(factory));
609 }
610
611 /**
612 * @see ICompilationUnit#findWorkingCopy(WorkingCopyOwner)
613 */
614 @Override
findWorkingCopy(WorkingCopyOwner workingCopyOwner)615 public ICompilationUnit findWorkingCopy(WorkingCopyOwner workingCopyOwner) {
616 CompilationUnit cu = new CompilationUnit((PackageFragment)this.parent, getElementName(), workingCopyOwner);
617 if (workingCopyOwner == DefaultWorkingCopyOwner.PRIMARY) {
618 return cu;
619 } else {
620 // must be a working copy
621 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = cu.getPerWorkingCopyInfo();
622 if (perWorkingCopyInfo != null) {
623 return perWorkingCopyInfo.getWorkingCopy();
624 } else {
625 return null;
626 }
627 }
628 }
629 /**
630 * @see ICompilationUnit#getAllTypes()
631 */
632 @Override
getAllTypes()633 public IType[] getAllTypes() throws JavaModelException {
634 IJavaElement[] types = getTypes();
635 ArrayList allTypes = new ArrayList(types.length);
636 ArrayList typesToTraverse = new ArrayList(types.length);
637 Collections.addAll(typesToTraverse, types);
638 while (!typesToTraverse.isEmpty()) {
639 IType type = (IType) typesToTraverse.get(0);
640 typesToTraverse.remove(type);
641 allTypes.add(type);
642 types = type.getTypes();
643 Collections.addAll(typesToTraverse, types);
644 }
645 IType[] arrayOfAllTypes = new IType[allTypes.size()];
646 allTypes.toArray(arrayOfAllTypes);
647 return arrayOfAllTypes;
648 }
649 /**
650 * @see IMember#getCompilationUnit()
651 */
652 @Override
getCompilationUnit()653 public ICompilationUnit getCompilationUnit() {
654 return this;
655 }
656 /**
657 * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getContents()
658 */
659 @Override
getContents()660 public char[] getContents() {
661 IBuffer buffer = getBufferManager().getBuffer(this);
662 if (buffer == null) {
663 // no need to force opening of CU to get the content
664 // also this cannot be a working copy, as its buffer is never closed while the working copy is alive
665 IFile file = (IFile) getResource();
666 // Get encoding from file
667 String encoding;
668 try {
669 encoding = file.getCharset();
670 } catch(CoreException ce) {
671 // do not use any encoding
672 encoding = null;
673 }
674 try {
675 return Util.getResourceContentsAsCharArray(file, encoding);
676 } catch (JavaModelException e) {
677 if (JavaModelManager.getJavaModelManager().abortOnMissingSource.get() == Boolean.TRUE) {
678 IOException ioException =
679 e.getJavaModelStatus().getCode() == IJavaModelStatusConstants.IO_EXCEPTION ?
680 (IOException)e.getException() :
681 new IOException(e.getMessage());
682 throw new AbortCompilationUnit(null, ioException, encoding);
683 } else {
684 Util.log(e, Messages.bind(Messages.file_notFound, file.getFullPath().toString()));
685 }
686 return CharOperation.NO_CHAR;
687 }
688 }
689 char[] contents = buffer.getCharacters();
690 if (contents == null) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=129814
691 if (JavaModelManager.getJavaModelManager().abortOnMissingSource.get() == Boolean.TRUE) {
692 IOException ioException = new IOException(Messages.buffer_closed);
693 IFile file = (IFile) getResource();
694 // Get encoding from file
695 String encoding;
696 try {
697 encoding = file.getCharset();
698 } catch(CoreException ce) {
699 // do not use any encoding
700 encoding = null;
701 }
702 throw new AbortCompilationUnit(null, ioException, encoding);
703 }
704 return CharOperation.NO_CHAR;
705 }
706 return contents;
707 }
708 /**
709 * A compilation unit has a corresponding resource unless it is contained
710 * in a jar.
711 *
712 * @see IJavaElement#getCorrespondingResource()
713 */
714 @Override
getCorrespondingResource()715 public IResource getCorrespondingResource() throws JavaModelException {
716 PackageFragmentRoot root = getPackageFragmentRoot();
717 if (root == null || root.isArchive()) {
718 return null;
719 } else {
720 return getUnderlyingResource();
721 }
722 }
723 /**
724 * @see ICompilationUnit#getElementAt(int)
725 */
726 @Override
getElementAt(int position)727 public IJavaElement getElementAt(int position) throws JavaModelException {
728
729 IJavaElement e= getSourceElementAt(position);
730 if (e == this) {
731 return null;
732 } else {
733 return e;
734 }
735 }
736 @Override
getElementName()737 public String getElementName() {
738 return this.name;
739 }
740 /**
741 * @see IJavaElement
742 */
743 @Override
getElementType()744 public int getElementType() {
745 return COMPILATION_UNIT;
746 }
747 /**
748 * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
749 */
750 @Override
getFileName()751 public char[] getFileName(){
752 return getPath().toString().toCharArray();
753 }
754
755 @Override
getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner)756 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
757 switch (token.charAt(0)) {
758 case JEM_IMPORTDECLARATION:
759 JavaElement container = (JavaElement)getImportContainer();
760 return container.getHandleFromMemento(token, memento, workingCopyOwner);
761 case JEM_PACKAGEDECLARATION:
762 if (!memento.hasMoreTokens()) return this;
763 String pkgName = memento.nextToken();
764 JavaElement pkgDecl = (JavaElement)getPackageDeclaration(pkgName);
765 return pkgDecl.getHandleFromMemento(memento, workingCopyOwner);
766 case JEM_TYPE:
767 if (!memento.hasMoreTokens()) return this;
768 String typeName = memento.nextToken();
769 JavaElement type = (JavaElement)getType(typeName);
770 return type.getHandleFromMemento(memento, workingCopyOwner);
771 case JEM_MODULE:
772 if (!memento.hasMoreTokens()) return this;
773 String modName = memento.nextToken();
774 JavaElement mod = new SourceModule(this, modName);
775 return mod.getHandleFromMemento(memento, workingCopyOwner);
776 }
777 return null;
778 }
779
780 /**
781 * @see JavaElement#getHandleMementoDelimiter()
782 */
783 @Override
getHandleMementoDelimiter()784 protected char getHandleMementoDelimiter() {
785 return JavaElement.JEM_COMPILATIONUNIT;
786 }
787 /**
788 * @see ICompilationUnit#getImport(String)
789 */
790 @Override
getImport(String importName)791 public IImportDeclaration getImport(String importName) {
792 return getImportContainer().getImport(importName);
793 }
794 /**
795 * @see ICompilationUnit#getImportContainer()
796 */
797 @Override
getImportContainer()798 public IImportContainer getImportContainer() {
799 return new ImportContainer(this);
800 }
801
802
803 /**
804 * @see ICompilationUnit#getImports()
805 */
806 @Override
getImports()807 public IImportDeclaration[] getImports() throws JavaModelException {
808 IImportContainer container= getImportContainer();
809 JavaModelManager manager = JavaModelManager.getJavaModelManager();
810 Object info = manager.getInfo(container);
811 if (info == null) {
812 if (manager.getInfo(this) != null)
813 // CU was opened, but no import container, then no imports
814 return NO_IMPORTS;
815 else {
816 open(null); // force opening of CU
817 info = manager.getInfo(container);
818 if (info == null)
819 // after opening, if no import container, then no imports
820 return NO_IMPORTS;
821 }
822 }
823 IJavaElement[] elements = ((ImportContainerInfo) info).children;
824 int length = elements.length;
825 IImportDeclaration[] imports = new IImportDeclaration[length];
826 System.arraycopy(elements, 0, imports, 0, length);
827 return imports;
828 }
829 /**
830 * @see IMember#getTypeRoot()
831 */
getTypeRoot()832 public ITypeRoot getTypeRoot() {
833 return this;
834 }
835 /**
836 * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getMainTypeName()
837 */
838 @Override
getMainTypeName()839 public char[] getMainTypeName(){
840 return Util.getNameWithoutJavaLikeExtension(getElementName()).toCharArray();
841 }
842 /**
843 * @see IWorkingCopy#getOriginal(IJavaElement)
844 * @deprecated
845 */
846 @Override
getOriginal(IJavaElement workingCopyElement)847 public IJavaElement getOriginal(IJavaElement workingCopyElement) {
848 // backward compatibility
849 if (!isWorkingCopy()) return null;
850 CompilationUnit cu = (CompilationUnit)workingCopyElement.getAncestor(COMPILATION_UNIT);
851 if (cu == null || !this.owner.equals(cu.owner)) {
852 return null;
853 }
854
855 return workingCopyElement.getPrimaryElement();
856 }
857 /**
858 * @see IWorkingCopy#getOriginalElement()
859 * @deprecated
860 */
861 @Override
getOriginalElement()862 public IJavaElement getOriginalElement() {
863 // backward compatibility
864 if (!isWorkingCopy()) return null;
865
866 return getPrimaryElement();
867 }
868
869 @Override
getOwner()870 public WorkingCopyOwner getOwner() {
871 return isPrimary() || !isWorkingCopy() ? null : this.owner;
872 }
873 /**
874 * @see ICompilationUnit#getPackageDeclaration(String)
875 */
876 @Override
getPackageDeclaration(String pkg)877 public IPackageDeclaration getPackageDeclaration(String pkg) {
878 return new PackageDeclaration(this, pkg);
879 }
880 /**
881 * @see ICompilationUnit#getPackageDeclarations()
882 */
883 @Override
getPackageDeclarations()884 public IPackageDeclaration[] getPackageDeclarations() throws JavaModelException {
885 ArrayList list = getChildrenOfType(PACKAGE_DECLARATION);
886 IPackageDeclaration[] array= new IPackageDeclaration[list.size()];
887 list.toArray(array);
888 return array;
889 }
890 /**
891 * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getPackageName()
892 */
893 @Override
getPackageName()894 public char[][] getPackageName() {
895 PackageFragment packageFragment = (PackageFragment) getParent();
896 if (packageFragment == null) return CharOperation.NO_CHAR_CHAR;
897 return Util.toCharArrays(packageFragment.names);
898 }
899
900 /**
901 * @see IJavaElement#getPath()
902 */
903 @Override
getPath()904 public IPath getPath() {
905 PackageFragmentRoot root = getPackageFragmentRoot();
906 if (root == null) return new Path(getElementName()); // working copy not in workspace
907 if (root.isArchive()) {
908 return root.getPath();
909 } else {
910 return getParent().getPath().append(getElementName());
911 }
912 }
913 /*
914 * Returns the per working copy info for the receiver, or null if none exist.
915 * Note: the use count of the per working copy info is NOT incremented.
916 */
getPerWorkingCopyInfo()917 public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() {
918 return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, false/*don't create*/, false/*don't record usage*/, null/*no problem requestor needed*/);
919 }
920
921 @Override
getPrimary()922 public ICompilationUnit getPrimary() {
923 return (ICompilationUnit)getPrimaryElement(true);
924 }
925
926 @Override
getPrimaryElement(boolean checkOwner)927 public IJavaElement getPrimaryElement(boolean checkOwner) {
928 if (checkOwner && isPrimary()) return this;
929 return new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY);
930 }
931
932 @Override
resource(PackageFragmentRoot root)933 public IResource resource(PackageFragmentRoot root) {
934 if (root == null) return null; // working copy not in workspace
935 return ((IContainer) ((Openable) this.parent).resource(root)).getFile(new Path(getElementName()));
936 }
937 /**
938 * @see ISourceReference#getSource()
939 */
940 @Override
getSource()941 public String getSource() throws JavaModelException {
942 IBuffer buffer = getBuffer();
943 if (buffer == null) return ""; //$NON-NLS-1$
944 return buffer.getContents();
945 }
946 /**
947 * @see ISourceReference#getSourceRange()
948 */
949 @Override
getSourceRange()950 public ISourceRange getSourceRange() throws JavaModelException {
951 return ((CompilationUnitElementInfo) getElementInfo()).getSourceRange();
952 }
953 /**
954 * @see ICompilationUnit#getType(String)
955 */
956 @Override
getType(String typeName)957 public IType getType(String typeName) {
958 return new SourceType(this, typeName);
959 }
960 /**
961 * @see ICompilationUnit#getTypes()
962 */
963 @Override
getTypes()964 public IType[] getTypes() throws JavaModelException {
965 ArrayList list = getChildrenOfType(TYPE);
966 IType[] array= new IType[list.size()];
967 list.toArray(array);
968 return array;
969 }
970 /**
971 * @see IJavaElement
972 */
973 @Override
getUnderlyingResource()974 public IResource getUnderlyingResource() throws JavaModelException {
975 if (isWorkingCopy() && !isPrimary()) return null;
976 return super.getUnderlyingResource();
977 }
978 /**
979 * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
980 * @deprecated
981 */
982 @Override
getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor)983 public IJavaElement getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
984
985 // if factory is null, default factory must be used
986 if (factory == null) factory = getBufferManager().getDefaultBufferFactory();
987
988 return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, pm);
989 }
990 /**
991 * @see IWorkingCopy#getWorkingCopy()
992 * @deprecated
993 */
994 @Override
getWorkingCopy()995 public IJavaElement getWorkingCopy() throws JavaModelException {
996 return getWorkingCopy(null);
997 }
998 /**
999 * @see ICompilationUnit#getWorkingCopy(IProgressMonitor)
1000 */
1001 @Override
getWorkingCopy(IProgressMonitor monitor)1002 public ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException {
1003 return getWorkingCopy(new WorkingCopyOwner() {/*non shared working copy*/}, null/*no problem requestor*/, monitor);
1004 }
1005 /**
1006 * @see ITypeRoot#getWorkingCopy(WorkingCopyOwner, IProgressMonitor)
1007 */
1008 @Override
getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor)1009 public ICompilationUnit getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor) throws JavaModelException {
1010 return getWorkingCopy(workingCopyOwner, null, monitor);
1011 }
1012 /**
1013 * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
1014 * @deprecated
1015 */
1016 @Override
getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor)1017 public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
1018 return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, monitor);
1019 }
1020 /**
1021 * @see ICompilationUnit#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
1022 * @deprecated
1023 */
1024 @Override
getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProblemRequestor problemRequestor, IProgressMonitor monitor)1025 public ICompilationUnit getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
1026 if (!isPrimary()) return this;
1027
1028 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1029
1030 CompilationUnit workingCopy = new CompilationUnit((PackageFragment)getParent(), getElementName(), workingCopyOwner);
1031 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo =
1032 manager.getPerWorkingCopyInfo(workingCopy, false/*don't create*/, true/*record usage*/, null/*not used since don't create*/);
1033 if (perWorkingCopyInfo != null) {
1034 return perWorkingCopyInfo.getWorkingCopy(); // return existing handle instead of the one created above
1035 }
1036 BecomeWorkingCopyOperation op = new BecomeWorkingCopyOperation(workingCopy, problemRequestor);
1037 op.runOperation(monitor);
1038 return workingCopy;
1039 }
1040 /**
1041 * @see Openable#hasBuffer()
1042 */
1043 @Override
hasBuffer()1044 protected boolean hasBuffer() {
1045 return true;
1046 }
1047
1048 @Override
hasResourceChanged()1049 public boolean hasResourceChanged() {
1050 if (!isWorkingCopy()) return false;
1051
1052 // if resource got deleted, then #getModificationStamp() will answer IResource.NULL_STAMP, which is always different from the cached
1053 // timestamp
1054 Object info = JavaModelManager.getJavaModelManager().getInfo(this);
1055 if (info == null) return false;
1056 IResource resource = getResource();
1057 if (resource == null) return false;
1058 return ((CompilationUnitElementInfo)info).timestamp != resource.getModificationStamp();
1059 }
1060 @Override
ignoreOptionalProblems()1061 public boolean ignoreOptionalProblems() {
1062 return getPackageFragmentRoot().ignoreOptionalProblems();
1063 }
1064 /**
1065 * @see IWorkingCopy#isBasedOn(IResource)
1066 * @deprecated
1067 */
1068 @Override
isBasedOn(IResource resource)1069 public boolean isBasedOn(IResource resource) {
1070 if (!isWorkingCopy()) return false;
1071 if (!getResource().equals(resource)) return false;
1072 return !hasResourceChanged();
1073 }
1074 /**
1075 * @see IOpenable#isConsistent()
1076 */
1077 @Override
isConsistent()1078 public boolean isConsistent() {
1079 return !JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().contains(this);
1080 }
isPrimary()1081 public boolean isPrimary() {
1082 return this.owner == DefaultWorkingCopyOwner.PRIMARY;
1083 }
1084 /**
1085 * @see Openable#isSourceElement()
1086 */
1087 @Override
isSourceElement()1088 protected boolean isSourceElement() {
1089 return true;
1090 }
validateCompilationUnit(IResource resource)1091 protected IStatus validateCompilationUnit(IResource resource) {
1092 IPackageFragmentRoot root = getPackageFragmentRoot();
1093 // root never null as validation is not done for working copies
1094 try {
1095 if (root.getKind() != IPackageFragmentRoot.K_SOURCE)
1096 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, root);
1097 } catch (JavaModelException e) {
1098 return e.getJavaModelStatus();
1099 }
1100 if (resource != null) {
1101 char[][] inclusionPatterns = ((PackageFragmentRoot)root).fullInclusionPatternChars();
1102 char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
1103 if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns))
1104 return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH, this);
1105 if (!resource.isAccessible())
1106 return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this);
1107 }
1108 IJavaProject project = getJavaProject();
1109 return JavaConventions.validateCompilationUnitName(getElementName(),project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true));
1110 }
1111
1112 @Override
isWorkingCopy()1113 public boolean isWorkingCopy() {
1114 // For backward compatibility, non primary working copies are always returning true; in removal
1115 // delta, clients can still check that element was a working copy before being discarded.
1116 return !isPrimary() || getPerWorkingCopyInfo() != null;
1117 }
1118 /**
1119 * @see IOpenable#makeConsistent(IProgressMonitor)
1120 */
1121 @Override
makeConsistent(IProgressMonitor monitor)1122 public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
1123 makeConsistent(NO_AST, false/*don't resolve bindings*/, 0 /* don't perform statements recovery */, null/*don't collect problems but report them*/, monitor);
1124 }
makeConsistent(int astLevel, boolean resolveBindings, int reconcileFlags, HashMap problems, IProgressMonitor monitor)1125 public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(int astLevel, boolean resolveBindings, int reconcileFlags, HashMap problems, IProgressMonitor monitor) throws JavaModelException {
1126 if (isConsistent()) return null;
1127
1128 try {
1129 JavaModelManager.getJavaModelManager().abortOnMissingSource.set(Boolean.TRUE);
1130 // create a new info and make it the current info
1131 // (this will remove the info and its children just before storing the new infos)
1132 if (astLevel != NO_AST || problems != null) {
1133 ASTHolderCUInfo info = new ASTHolderCUInfo();
1134 info.astLevel = astLevel;
1135 info.resolveBindings = resolveBindings;
1136 info.reconcileFlags = reconcileFlags;
1137 info.problems = problems;
1138 openWhenClosed(info, true, monitor);
1139 org.eclipse.jdt.core.dom.CompilationUnit result = info.ast;
1140 info.ast = null;
1141 return result;
1142 } else {
1143 openWhenClosed(createElementInfo(), true, monitor);
1144 return null;
1145 }
1146 } finally {
1147 JavaModelManager.getJavaModelManager().abortOnMissingSource.set(null);
1148 }
1149 }
1150 /**
1151 * @see ISourceManipulation#move(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
1152 */
1153 @Override
move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor)1154 public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
1155 if (container == null) {
1156 throw new IllegalArgumentException(Messages.operation_nullContainer);
1157 }
1158 IJavaElement[] elements= new IJavaElement[] {this};
1159 IJavaElement[] containers= new IJavaElement[] {container};
1160
1161 String[] renamings= null;
1162 if (rename != null) {
1163 renamings= new String[] {rename};
1164 }
1165 getJavaModel().move(elements, containers, null, renamings, force, monitor);
1166 }
1167
1168 /**
1169 * @see Openable#openBuffer(IProgressMonitor, Object)
1170 */
1171 @Override
openBuffer(IProgressMonitor pm, Object info)1172 protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
1173
1174 // create buffer
1175 BufferManager bufManager = getBufferManager();
1176 boolean isWorkingCopy = isWorkingCopy();
1177 IBuffer buffer =
1178 isWorkingCopy
1179 ? this.owner.createBuffer(this)
1180 : BufferManager.createBuffer(this);
1181 if (buffer == null) return null;
1182
1183 ICompilationUnit original = null;
1184 boolean mustSetToOriginalContent = false;
1185 if (isWorkingCopy) {
1186 // ensure that isOpen() is called outside the bufManager synchronized block
1187 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=237772
1188 mustSetToOriginalContent = !isPrimary() && (original = new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY)).isOpen() ;
1189 }
1190
1191 // synchronize to ensure that 2 threads are not putting 2 different buffers at the same time
1192 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=146331
1193 IBuffer existingBuffer;
1194 synchronized(bufManager) {
1195 existingBuffer = bufManager.getBuffer(this);
1196 if (existingBuffer == null) {
1197 // set the buffer source
1198 if (buffer.getCharacters() == null) {
1199 if (isWorkingCopy) {
1200 if (mustSetToOriginalContent) {
1201 buffer.setContents(original.getSource());
1202 } else {
1203 IFile file = (IFile)getResource();
1204 if (file == null || !file.exists()) {
1205 // initialize buffer with empty contents
1206 buffer.setContents(CharOperation.NO_CHAR);
1207 } else {
1208 buffer.setContents(Util.getResourceContentsAsCharArray(file));
1209 }
1210 }
1211 } else {
1212 IFile file = (IFile)getResource();
1213 if (file == null || !file.exists()) throw newNotPresentException();
1214 buffer.setContents(Util.getResourceContentsAsCharArray(file));
1215 }
1216 }
1217
1218 // add buffer to buffer cache
1219 // note this may cause existing buffers to be removed from the buffer cache, but only primary compilation unit's buffer
1220 // can be closed, thus no call to a client's IBuffer#close() can be done in this synchronized block.
1221 bufManager.addBuffer(buffer);
1222
1223 // listen to buffer changes
1224 buffer.addBufferChangedListener(this);
1225 }
1226 }
1227 if(existingBuffer != null) {
1228 buffer.close();
1229 return existingBuffer;
1230 }
1231 return buffer;
1232 }
1233 @Override
openAncestors(HashMap newElements, IProgressMonitor monitor)1234 protected void openAncestors(HashMap newElements, IProgressMonitor monitor) throws JavaModelException {
1235 if (!isWorkingCopy()) {
1236 super.openAncestors(newElements, monitor);
1237 }
1238 // else don't open ancestors for a working copy to speed up the first becomeWorkingCopy
1239 // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=89411)
1240 }
1241 /*
1242 * @see #cloneCachingContents()
1243 */
originalFromClone()1244 public CompilationUnit originalFromClone() {
1245 return this;
1246 }
1247 /**
1248 * @see ICompilationUnit#reconcile()
1249 * @deprecated
1250 */
1251 @Override
reconcile()1252 public IMarker[] reconcile() throws JavaModelException {
1253 reconcile(NO_AST, false/*don't force problem detection*/, false, null/*use primary owner*/, null/*no progress monitor*/);
1254 return null;
1255 }
1256 /**
1257 * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
1258 */
1259 @Override
reconcile(boolean forceProblemDetection, IProgressMonitor monitor)1260 public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException {
1261 reconcile(NO_AST, forceProblemDetection? ICompilationUnit.FORCE_PROBLEM_DETECTION : 0, null/*use primary owner*/, monitor);
1262 }
1263
1264 /**
1265 * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
1266 * @since 3.0
1267 */
1268 @Override
reconcile( int astLevel, boolean forceProblemDetection, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor)1269 public org.eclipse.jdt.core.dom.CompilationUnit reconcile(
1270 int astLevel,
1271 boolean forceProblemDetection,
1272 WorkingCopyOwner workingCopyOwner,
1273 IProgressMonitor monitor) throws JavaModelException {
1274 return reconcile(astLevel, forceProblemDetection? ICompilationUnit.FORCE_PROBLEM_DETECTION : 0, workingCopyOwner, monitor);
1275 }
1276
1277 /**
1278 * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
1279 * @since 3.0
1280 */
1281 @Override
reconcile( int astLevel, boolean forceProblemDetection, boolean enableStatementsRecovery, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor)1282 public org.eclipse.jdt.core.dom.CompilationUnit reconcile(
1283 int astLevel,
1284 boolean forceProblemDetection,
1285 boolean enableStatementsRecovery,
1286 WorkingCopyOwner workingCopyOwner,
1287 IProgressMonitor monitor) throws JavaModelException {
1288 int flags = 0;
1289 if (forceProblemDetection) flags |= ICompilationUnit.FORCE_PROBLEM_DETECTION;
1290 if (enableStatementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
1291 return reconcile(astLevel, flags, workingCopyOwner, monitor);
1292 }
1293
1294 @Override
reconcile( int astLevel, int reconcileFlags, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor)1295 public org.eclipse.jdt.core.dom.CompilationUnit reconcile(
1296 int astLevel,
1297 int reconcileFlags,
1298 WorkingCopyOwner workingCopyOwner,
1299 IProgressMonitor monitor)
1300 throws JavaModelException {
1301
1302 if (!isWorkingCopy()) return null; // Reconciling is not supported on non working copies
1303 if (workingCopyOwner == null) workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
1304
1305
1306 PerformanceStats stats = null;
1307 if(ReconcileWorkingCopyOperation.PERF) {
1308 stats = PerformanceStats.getStats(JavaModelManager.RECONCILE_PERF, this);
1309 stats.startRun(new String(getFileName()));
1310 }
1311 ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, astLevel, reconcileFlags, workingCopyOwner);
1312 JavaModelManager manager = JavaModelManager.getJavaModelManager();
1313 try {
1314 manager.cacheZipFiles(this); // cache zip files for performance (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=134172)
1315 op.runOperation(monitor);
1316 } finally {
1317 manager.flushZipFiles(this);
1318 }
1319 if(ReconcileWorkingCopyOperation.PERF) {
1320 stats.endRun();
1321 }
1322 return op.ast;
1323 }
1324
1325 /**
1326 * @see ISourceManipulation#rename(String, boolean, IProgressMonitor)
1327 */
1328 @Override
rename(String newName, boolean force, IProgressMonitor monitor)1329 public void rename(String newName, boolean force, IProgressMonitor monitor) throws JavaModelException {
1330 if (newName == null) {
1331 throw new IllegalArgumentException(Messages.operation_nullName);
1332 }
1333 IJavaElement[] elements= new IJavaElement[] {this};
1334 IJavaElement[] dests= new IJavaElement[] {getParent()};
1335 String[] renamings= new String[] {newName};
1336 getJavaModel().rename(elements, dests, renamings, force, monitor);
1337 }
1338
1339 @Override
restore()1340 public void restore() throws JavaModelException {
1341
1342 if (!isWorkingCopy()) return;
1343
1344 CompilationUnit original = (CompilationUnit) getOriginalElement();
1345 IBuffer buffer = getBuffer();
1346 if (buffer == null) return;
1347 buffer.setContents(original.getContents());
1348 updateTimeStamp(original);
1349 makeConsistent(null);
1350 }
1351 /**
1352 * @see IOpenable
1353 */
1354 @Override
save(IProgressMonitor pm, boolean force)1355 public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
1356 if (isWorkingCopy()) {
1357 // no need to save the buffer for a working copy (this is a noop)
1358 reconcile(); // not simply makeConsistent, also computes fine-grain deltas
1359 // in case the working copy is being reconciled already (if not it would miss
1360 // one iteration of deltas).
1361 } else {
1362 super.save(pm, force);
1363 }
1364 }
1365 /**
1366 * Debugging purposes
1367 */
1368 @Override
toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo)1369 protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) {
1370 if (!isPrimary()) {
1371 buffer.append(tabString(tab));
1372 buffer.append("[Working copy] "); //$NON-NLS-1$
1373 toStringName(buffer);
1374 } else {
1375 if (isWorkingCopy()) {
1376 buffer.append(tabString(tab));
1377 buffer.append("[Working copy] "); //$NON-NLS-1$
1378 toStringName(buffer);
1379 if (info == null) {
1380 buffer.append(" (not open)"); //$NON-NLS-1$
1381 }
1382 } else {
1383 super.toStringInfo(tab, buffer, info, showResolvedInfo);
1384 }
1385 }
1386 }
1387 /*
1388 * Assume that this is a working copy
1389 */
updateTimeStamp(CompilationUnit original)1390 protected void updateTimeStamp(CompilationUnit original) throws JavaModelException {
1391 long timeStamp =
1392 ((IFile) original.getResource()).getModificationStamp();
1393 if (timeStamp == IResource.NULL_STAMP) {
1394 throw new JavaModelException(
1395 new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE));
1396 }
1397 ((CompilationUnitElementInfo) getElementInfo()).timestamp = timeStamp;
1398 }
1399
1400 @Override
validateExistence(IResource underlyingResource)1401 protected IStatus validateExistence(IResource underlyingResource) {
1402 // check if this compilation unit can be opened
1403 if (!isWorkingCopy()) { // no check is done on root kind or exclusion pattern for working copies
1404 IStatus status = validateCompilationUnit(underlyingResource);
1405 if (!status.isOK())
1406 return status;
1407 }
1408
1409 // prevents reopening of non-primary working copies (they are closed when they are discarded and should not be reopened)
1410 if (!isPrimary() && getPerWorkingCopyInfo() == null) {
1411 return newDoesNotExistStatus();
1412 }
1413
1414 return JavaModelStatus.VERIFIED_OK;
1415 }
1416
1417 @Override
getNameRange()1418 public ISourceRange getNameRange() {
1419 return null;
1420 }
1421
1422
1423 @Override
getModule()1424 public IModuleDescription getModule() throws JavaModelException {
1425 if (TypeConstants.MODULE_INFO_FILE_NAME_STRING.equals(getElementName()))
1426 return ((CompilationUnitElementInfo) getElementInfo()).getModule();
1427 return null;
1428 }
1429
1430 @Override
getModuleName()1431 public char[] getModuleName() {
1432 try {
1433 IModuleDescription module = getModule();
1434 if (module == null) {
1435 JavaProject project = (JavaProject) getAncestor(IJavaElement.JAVA_PROJECT);
1436 module = project.getModuleDescription();
1437 }
1438 if (module != null)
1439 return module.getElementName().toCharArray();
1440 } catch (JavaModelException e) {
1441 // TODO Auto-generated catch block
1442 e.printStackTrace();
1443 }
1444 return null;
1445 }
1446 }
1447