1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
13 import net.sourceforge.phpdt.core.BufferChangedEvent;
14 import net.sourceforge.phpdt.core.IBuffer;
15 import net.sourceforge.phpdt.core.IBufferChangedListener;
16 import net.sourceforge.phpdt.core.IJavaElement;
17 import net.sourceforge.phpdt.core.IOpenable;
18 import net.sourceforge.phpdt.core.JavaModelException;
20 import org.eclipse.core.resources.IContainer;
21 import org.eclipse.core.resources.IResource;
22 import org.eclipse.core.runtime.IProgressMonitor;
25 * Abstract class for implementations of java elements which are IOpenable.
30 public abstract class Openable extends JavaElement implements IOpenable, IBufferChangedListener {
32 protected Openable(int type, IJavaElement parent, String name) {
33 super(type, parent, name);
36 * The buffer associated with this element has changed. Registers
37 * this element as being out of synch with its buffer's contents.
38 * If the buffer has been closed, this element is set as NOT out of
39 * synch with the contents.
41 * @see IBufferChangedListener
43 public void bufferChanged(BufferChangedEvent event) {
44 if (event.getBuffer().isClosed()) {
45 // JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
46 // getBufferManager().removeBuffer(event.getBuffer());
48 // JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().put(this, this);
52 // * Updates the info objects for this element and all of its children by
53 // * removing the current infos, generating new infos, and then placing
54 // * the new infos into the Java Model cache tables.
56 //protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException {
58 // if (monitor != null && monitor.isCanceled()) return;
60 // // remove existing (old) infos
62 // HashMap newElements = new HashMap(11);
63 // info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
64 // JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
65 // for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
66 // IJavaElement key = (IJavaElement) iter.next();
67 // Object value = newElements.get(key);
68 // JavaModelManager.getJavaModelManager().putInfo(key, value);
71 // // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
72 // // to be flushed. Might lead to performance issues.
73 // // see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type
74 // JavaModelManager.getJavaModelManager().putInfo(this, info);
77 // * Close the buffer associated with this element, if any.
79 //protected void closeBuffer(OpenableElementInfo info) {
80 // if (!hasBuffer()) return; // nothing to do
81 // IBuffer buffer = null;
82 // buffer = getBufferManager().getBuffer(this);
83 // if (buffer != null) {
85 // buffer.removeBufferChangedListener(this);
89 // * This element is being closed. Do any necessary cleanup.
91 //protected void closing(Object info) throws JavaModelException {
92 // OpenableElementInfo openableInfo = (OpenableElementInfo) info;
93 // closeBuffer(openableInfo);
94 // super.closing(info);
99 //protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, ICompletionRequestor requestor) throws JavaModelException {
100 // if (requestor == null) {
101 // throw new IllegalArgumentException(Util.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
103 // IBuffer buffer = getBuffer();
104 // if (buffer == null) {
107 // if (position < -1 || position > buffer.getLength()) {
108 // throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
110 // JavaProject project = (JavaProject) getJavaProject();
111 // SearchableEnvironment environment = (SearchableEnvironment) project.getSearchableNameEnvironment();
112 // NameLookup nameLookup = project.getNameLookup();
113 // environment.unitToSkip = unitToSkip;
115 // CompletionEngine engine = new CompletionEngine(environment, new CompletionRequestorWrapper(requestor,nameLookup), project.getOptions(true), project);
116 // engine.complete(cu, position, 0);
117 // environment.unitToSkip = null;
120 // * @see ICodeAssist
122 //protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length) throws JavaModelException {
123 // SelectionRequestor requestor= new SelectionRequestor(((JavaProject)getJavaProject()).getNameLookup(), this);
124 // this.codeSelect(cu, offset, length, requestor);
125 // return requestor.getElements();
128 // * @see ICodeAssist
130 //protected void codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, ISelectionRequestor requestor) throws JavaModelException {
131 // IBuffer buffer = getBuffer();
132 // if (buffer == null) {
135 // int end= buffer.getLength();
136 // if (offset < 0 || length < 0 || offset + length > end ) {
137 // throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
140 // // fix for 1FVGGKF
141 // JavaProject project = (JavaProject)getJavaProject();
142 // ISearchableNameEnvironment environment = project.getSearchableNameEnvironment();
144 // // fix for 1FVXGDK
145 // SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
146 // engine.select(cu, offset, offset + length - 1);
149 // * Returns a new element info for this element.
151 //protected OpenableElementInfo createElementInfo() {
152 // return new OpenableElementInfo();
156 // * Builds this element's structure and properties in the given
157 // * info object, based on this element's current contents (reuse buffer
158 // * contents if this element has an open buffer, or resource contents
159 // * if this element does not have an open buffer). Children
160 // * are placed in the given newElements table (note, this element
161 // * has already been placed in the newElements table). Returns true
162 // * if successful, or false if an error is encountered while determining
163 // * the structure of this element.
165 //protected abstract boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException;
167 * Note: a buffer with no unsaved changes can be closed by the Java Model
168 * since it has a finite number of buffers allowed open at one time. If this
169 * is the first time a request is being made for the buffer, an attempt is
170 * made to create and fill this element's buffer. If the buffer has been
171 * closed since it was first opened, the buffer is re-created.
175 public IBuffer getBuffer() throws JavaModelException {
177 // ensure element is open
181 IBuffer buffer = getBufferManager().getBuffer(this);
182 if (buffer == null) {
183 // try to (re)open a buffer
184 buffer = openBuffer(null);
193 // * Answers the buffer factory to use for creating new buffers
195 //public IBufferFactory getBufferFactory(){
196 // return getBufferManager().getDefaultBufferFactory();
200 * Returns the buffer manager for this element.
202 protected BufferManager getBufferManager() {
203 return BufferManager.getDefaultBufferManager();
206 * Return my underlying resource. Elements that may not have a
207 * corresponding resource must override this method.
211 public IResource getCorrespondingResource() throws JavaModelException {
212 return getUnderlyingResource();
215 // * @see IJavaElement
217 //public IOpenable getOpenable() {
226 public IResource getUnderlyingResource() throws JavaModelException {
227 IResource parentResource = fParent.getUnderlyingResource();
228 if (parentResource == null) {
231 int type = parentResource.getType();
232 if (type == IResource.FOLDER || type == IResource.PROJECT) {
233 IContainer folder = (IContainer) parentResource;
234 IResource resource = folder.findMember(fName);
235 if (resource == null) {
236 throw newNotPresentException();
241 return parentResource;
245 //public boolean exists() {
247 // IPackageFragmentRoot root = this.getPackageFragmentRoot();
248 // if (root == null || root == this || !root.isArchive()) {
249 // return parentExists() && resourceExists();
251 // return super.exists();
256 * Returns true if this element may have an associated source buffer,
257 * otherwise false. Subclasses must override as required.
259 protected boolean hasBuffer() {
265 //public boolean hasChildren() throws JavaModelException {
266 // return getChildren().length > 0;
271 //public boolean hasUnsavedChanges() throws JavaModelException{
273 // if (isReadOnly() || !isOpen()) {
276 // IBuffer buf = this.getBuffer();
277 // if (buf != null && buf.hasUnsavedChanges()) {
280 // // for package fragments, package fragment roots, and projects must check open buffers
281 // // to see if they have an child with unsaved changes
282 // if (fLEType == PACKAGE_FRAGMENT ||
283 // fLEType == PACKAGE_FRAGMENT_ROOT ||
284 // fLEType == JAVA_PROJECT ||
285 // fLEType == JAVA_MODEL) { // fix for 1FWNMHH
286 // Enumeration openBuffers= getBufferManager().getOpenBuffers();
287 // while (openBuffers.hasMoreElements()) {
288 // IBuffer buffer= (IBuffer)openBuffers.nextElement();
289 // if (buffer.hasUnsavedChanges()) {
290 // IJavaElement owner= (IJavaElement)buffer.getOwner();
291 // if (isAncestorOf(owner)) {
301 * Subclasses must override as required.
305 public boolean isConsistent() throws JavaModelException {
312 public boolean isOpen() {
313 // TODO isOpen - Openable needs JavaModelManager
314 // synchronized(JavaModelManager.getJavaModelManager()){
315 // return JavaModelManager.getJavaModelManager().getInfo(this) != null;
320 // * Returns true if this represents a source element.
321 // * Openable source elements have an associated buffer created
322 // * when they are opened.
324 //protected boolean isSourceElement() {
330 //public void makeConsistent(IProgressMonitor pm) throws JavaModelException {
331 // if (!isConsistent()) {
332 // buildStructure((OpenableElementInfo)getElementInfo(), pm);
338 //public void open(IProgressMonitor pm) throws JavaModelException {
340 // // TODO: need to synchronize (IOpenable.open(IProgressMonitor) is API
341 // // TODO: could use getElementInfo instead
342 // this.openWhenClosed(pm);
347 * Opens a buffer on the contents of this element, and returns
348 * the buffer, or returns <code>null</code> if opening fails.
349 * By default, do nothing - subclasses that have buffers
350 * must override as required.
352 protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
357 // * Open the parent element if necessary
360 //protected void openParent(IProgressMonitor pm) throws JavaModelException {
362 // Openable openableParent = (Openable)getOpenableParent();
363 // if (openableParent != null) {
364 // if (!openableParent.isOpen()){
365 // openableParent.openWhenClosed(pm);
371 // * Open an <code>Openable</code> that is known to be closed (no check for <code>isOpen()</code>).
373 //protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
376 // if (JavaModelManager.VERBOSE){
377 // System.out.println("OPENING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
380 // // 1) Parent must be open - open the parent if necessary
383 // // 2) create the new element info and open a buffer if needed
384 // OpenableElementInfo info = createElementInfo();
385 // if (isSourceElement()) {
386 // this.openBuffer(pm);
389 // // 3) build the structure of the openable
390 // buildStructure(info, pm);
392 // // 4) anything special
395 // if (JavaModelManager.VERBOSE) {
396 // System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
397 // System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
400 // // if any problems occuring openning the element, ensure that it's info
401 // // does not remain in the cache (some elements, pre-cache their info
402 // // as they are being opened).
403 // } catch (JavaModelException e) {
404 // JavaModelManager.getJavaModelManager().removeInfo(this);
410 // * Answers true if the parent exists (null parent is answering true)
413 //protected boolean parentExists(){
415 // IJavaElement parent = this.getParent();
416 // if (parent == null) return true;
417 // return parent.exists();
421 // * Returns whether the corresponding resource or associated file exists
423 //protected boolean resourceExists() {
424 // IWorkspace workspace = ResourcesPlugin.getWorkspace();
425 // if (workspace == null) return false; // workaround for http://bugs.eclipse.org/bugs/show_bug.cgi?id=34069
427 // JavaModel.getTarget(
428 // workspace.getRoot(),
429 // this.getPath().makeRelative(), // ensure path is relative (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
436 //public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
437 // if (isReadOnly() || this.getResource().isReadOnly()) {
438 // throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
440 // IBuffer buf = getBuffer();
441 // if (buf != null) { // some Openables (like a JavaProject) don't have a buffer
442 // buf.save(pm, force);
443 // this.makeConsistent(pm); // update the element info of this element
448 * Find enclosing package fragment root if any
450 public PackageFragmentRoot getPackageFragmentRoot() {
451 IJavaElement current = this;
453 if (current instanceof PackageFragmentRoot) return (PackageFragmentRoot)current;
454 current = current.getParent();
455 } while(current != null);
459 // * @see ICodeAssist
460 // * @deprecated - use codeComplete(ICompilationUnit, ICompilationUnit, int, ICompletionRequestor) instead
462 //protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, final ICodeCompletionRequestor requestor) throws JavaModelException {
464 // if (requestor == null){
465 // codeComplete(cu, unitToSkip, position, (ICompletionRequestor)null);
472 // new ICompletionRequestor(){
473 // public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
475 // public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
476 // requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
478 // public void acceptError(IProblem error) {
479 // if (true) return; // was disabled in 1.0
482 // IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
483 // marker.setAttribute(IJavaModelMarker.ID, error.getID());
484 // marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
485 // marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
486 // marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
487 // marker.setAttribute(IMarker.MESSAGE, error.getMessage());
488 // marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
489 // requestor.acceptError(marker);
490 // } catch(CoreException e){
493 // public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
494 // requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
496 // public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
497 // requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
499 // public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
500 // requestor.acceptKeyword(keywordName, completionStart, completionEnd);
502 // public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
503 // requestor.acceptLabel(labelName, completionStart, completionEnd);
505 // public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
508 // 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){
509 // // skip parameter names
510 // requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
512 // 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){
515 // public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
516 // requestor.acceptModifier(modifierName, completionStart, completionEnd);
518 // public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
519 // requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
521 // public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
522 // requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
524 // public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance){