+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package net.sourceforge.phpdt.internal.ui.text.folding;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import net.sourceforge.phpdt.core.ElementChangedEvent;
-import net.sourceforge.phpdt.core.IElementChangedListener;
-import net.sourceforge.phpdt.core.IJavaElement;
-import net.sourceforge.phpdt.core.IJavaElementDelta;
-import net.sourceforge.phpdt.core.IParent;
-import net.sourceforge.phpdt.core.ISourceRange;
-import net.sourceforge.phpdt.core.ISourceReference;
-import net.sourceforge.phpdt.core.IType;
-import net.sourceforge.phpdt.core.JavaCore;
-import net.sourceforge.phpdt.core.JavaModelException;
-import net.sourceforge.phpdt.core.ToolFactory;
-import net.sourceforge.phpdt.core.compiler.IScanner;
-import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
-import net.sourceforge.phpdt.core.compiler.InvalidInputException;
-import net.sourceforge.phpdt.ui.IWorkingCopyManager;
-import net.sourceforge.phpdt.ui.PreferenceConstants;
-import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
-import net.sourceforge.phpeclipse.PHPeclipsePlugin;
-import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
-import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
-
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.Position;
-import org.eclipse.jface.text.Region;
-import org.eclipse.jface.text.source.Annotation;
-import org.eclipse.jface.text.source.IAnnotationModel;
-import org.eclipse.jface.text.source.projection.IProjectionListener;
-import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
-import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
-import org.eclipse.jface.text.source.projection.ProjectionViewer;
-import org.eclipse.ui.texteditor.IDocumentProvider;
-import org.eclipse.ui.texteditor.ITextEditor;
-
-
-/**
- * Updates the projection model of a class file or compilation unit.
- *
- * @since 3.0
- */
-public class DefaultJavaFoldingStructureProvider implements IProjectionListener, IJavaFoldingStructureProvider {
-
- private static class JavaProjectionAnnotation extends ProjectionAnnotation {
-
- private IJavaElement fJavaElement;
- private boolean fIsComment;
-
- public JavaProjectionAnnotation(IJavaElement element, boolean isCollapsed, boolean isComment) {
- super(isCollapsed);
- fJavaElement= element;
- fIsComment= isComment;
- }
-
- public IJavaElement getElement() {
- return fJavaElement;
- }
-
- public void setElement(IJavaElement element) {
- fJavaElement= element;
- }
-
- public boolean isComment() {
- return fIsComment;
- }
-
- public void setIsComment(boolean isComment) {
- fIsComment= isComment;
- }
- }
-
- private class ElementChangedListener implements IElementChangedListener {
-
- /*
- * @see net.sourceforge.phpdt.core.IElementChangedListener#elementChanged(net.sourceforge.phpdt.core.ElementChangedEvent)
- */
- public void elementChanged(ElementChangedEvent e) {
- IJavaElementDelta delta= findElement(fInput, e.getDelta());
- if (delta != null)
- processDelta(delta);
- }
-
- private IJavaElementDelta findElement(IJavaElement target, IJavaElementDelta delta) {
-
- if (delta == null || target == null)
- return null;
-
- IJavaElement element= delta.getElement();
-
- if (element.getElementType() > IJavaElement.CLASS_FILE)
- return null;
-
- if (target.equals(element))
- return delta;
-
- IJavaElementDelta[] children= delta.getAffectedChildren();
- if (children == null || children.length == 0)
- return null;
-
- for (int i= 0; i < children.length; i++) {
- IJavaElementDelta d= findElement(target, children[i]);
- if (d != null)
- return d;
- }
-
- return null;
- }
- }
-
-
- private IDocument fCachedDocument;
-
- private ITextEditor fEditor;
- private ProjectionViewer fViewer;
- private IJavaElement fInput;
- private IElementChangedListener fElementListener;
-
- private boolean fAllowCollapsing= false;
- private boolean fCollapseJavadoc= false;
- private boolean fCollapseImportContainer= true;
- private boolean fCollapseInnerTypes= true;
- private boolean fCollapseMethods= false;
-
- public DefaultJavaFoldingStructureProvider() {
- }
-
- public void install(ITextEditor editor, ProjectionViewer viewer) {
- if (editor instanceof PHPEditor) {
- fEditor= editor;
- fViewer= viewer;
- fViewer.addProjectionListener(this);
- }
- }
-
- public void uninstall() {
- if (isInstalled()) {
- projectionDisabled();
- fViewer.removeProjectionListener(this);
- fViewer= null;
- fEditor= null;
- }
- }
-
- protected boolean isInstalled() {
- return fEditor != null;
- }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled()
- */
- public void projectionEnabled() {
- if (fEditor instanceof PHPEditor) {
- initialize();
- fElementListener= new ElementChangedListener();
- JavaCore.addElementChangedListener(fElementListener);
- }
- }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionDisabled()
- */
- public void projectionDisabled() {
- fCachedDocument= null;
- if (fElementListener != null) {
- JavaCore.removeElementChangedListener(fElementListener);
- fElementListener= null;
- }
- }
-
- public void initialize() {
-
- if (!isInstalled())
- return;
-
- initializePreferences();
-
- try {
-
- IDocumentProvider provider= fEditor.getDocumentProvider();
- fCachedDocument= provider.getDocument(fEditor.getEditorInput());
- fAllowCollapsing= true;
-
- if (fEditor instanceof PHPUnitEditor) {
- IWorkingCopyManager manager= PHPeclipsePlugin.getDefault().getWorkingCopyManager();
- fInput= manager.getWorkingCopy(fEditor.getEditorInput());
- }
-// else if (fEditor instanceof ClassFileEditor) {
-// IClassFileEditorInput editorInput= (IClassFileEditorInput) fEditor.getEditorInput();
-// fInput= editorInput.getClassFile();
-// }
-
- if (fInput != null) {
- ProjectionAnnotationModel model= (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
- if (model != null) {
- Map additions= computeAdditions((IParent) fInput);
- model.removeAllAnnotations();
- model.replaceAnnotations(null, additions);
- }
- }
-
- } finally {
- fCachedDocument= null;
- fAllowCollapsing= false;
- }
- }
-
- private void initializePreferences() {
- IPreferenceStore store= PHPeclipsePlugin.getDefault().getPreferenceStore();
- fCollapseInnerTypes= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_INNERTYPES);
- fCollapseImportContainer= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_IMPORTS);
- fCollapseJavadoc= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_JAVADOC);
- fCollapseMethods= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS);
- }
-
- private Map computeAdditions(IParent parent) {
- Map map= new HashMap();
- try {
- computeAdditions(parent.getChildren(), map);
- } catch (JavaModelException x) {
- }
- return map;
- }
-
- private void computeAdditions(IJavaElement[] elements, Map map) throws JavaModelException {
- for (int i= 0; i < elements.length; i++) {
- IJavaElement element= elements[i];
-
- computeAdditions(element, map);
-
- if (element instanceof IParent) {
- IParent parent= (IParent) element;
- computeAdditions(parent.getChildren(), map);
- }
- }
- }
-
- private void computeAdditions(IJavaElement element, Map map) {
-
- boolean createProjection= false;
-
- boolean collapse= false;
- switch (element.getElementType()) {
-
- case IJavaElement.IMPORT_CONTAINER:
- collapse= fAllowCollapsing && fCollapseImportContainer;
- createProjection= true;
- break;
- case IJavaElement.TYPE:
- collapse= fAllowCollapsing && fCollapseInnerTypes && isInnerType((IType) element);
- createProjection= true;
- break;
- case IJavaElement.METHOD:
- collapse= fAllowCollapsing && fCollapseMethods;
- createProjection= true;
- break;
- }
-
- if (createProjection) {
- IRegion[] regions= computeProjectionRanges(element);
- if (regions != null) {
- // comments
- for (int i= 0; i < regions.length - 1; i++) {
- Position position= createProjectionPosition(regions[i]);
- if (position != null)
- map.put(new JavaProjectionAnnotation(element, fAllowCollapsing && fCollapseJavadoc, true), position);
- }
- // code
- Position position= createProjectionPosition(regions[regions.length - 1]);
- if (position != null)
- map.put(new JavaProjectionAnnotation(element, collapse, false), position);
- }
- }
- }
-
- private boolean isInnerType(IType type) {
-
- try {
- return type.isMember();
- } catch (JavaModelException x) {
- IJavaElement parent= type.getParent();
- if (parent != null) {
- int parentType= parent.getElementType();
- return (parentType != IJavaElement.COMPILATION_UNIT && parentType != IJavaElement.CLASS_FILE);
- }
- }
-
- return false;
- }
-
- private IRegion[] computeProjectionRanges(IJavaElement element) {
-
- try {
- if (element instanceof ISourceReference) {
- ISourceReference reference= (ISourceReference) element;
- ISourceRange range= reference.getSourceRange();
- String contents= reference.getSource();
- if (contents == null)
- return null;
-
- IScanner scanner= ToolFactory.createScanner(true, false, false);//, false);
- scanner.setSource(contents.toCharArray());
- List regions= new ArrayList();
- int shift= range.getOffset();
- int start= shift;
- while (true) {
-
- int token= scanner.getNextToken();
- start= shift + scanner.getCurrentTokenStartPosition();
-
- switch (token) {
- case ITerminalSymbols.TokenNameCOMMENT_PHPDOC: // COMMENT_JAVADOC:
- case ITerminalSymbols.TokenNameCOMMENT_BLOCK: {
- int end= shift + scanner.getCurrentTokenEndPosition() + 1;
- regions.add(new Region(start, end - start));
- }
- case ITerminalSymbols.TokenNameCOMMENT_LINE:
- continue;
- }
-
- break;
- }
-
- regions.add(new Region(start, range.getOffset() + range.getLength() - start));
-
- if (regions.size() > 0) {
- IRegion[] result= new IRegion[regions.size()];
- regions.toArray(result);
- return result;
- }
- }
- } catch (JavaModelException e) {
- } catch (InvalidInputException e) {
- }
-
- return null;
- }
-
- private Position createProjectionPosition(IRegion region) {
-
- if (fCachedDocument == null)
- return null;
-
- try {
-
- int start= fCachedDocument.getLineOfOffset(region.getOffset());
- int end= fCachedDocument.getLineOfOffset(region.getOffset() + region.getLength());
- if (start != end) {
- int offset= fCachedDocument.getLineOffset(start);
- int endOffset= fCachedDocument.getLineOffset(end + 1);
- return new Position(offset, endOffset - offset);
- }
-
- } catch (BadLocationException x) {
- }
-
- return null;
- }
-
- protected void processDelta(IJavaElementDelta delta) {
-
- if (!isInstalled())
- return;
-
- ProjectionAnnotationModel model= (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
- if (model == null)
- return;
-
- try {
-
- IDocumentProvider provider= fEditor.getDocumentProvider();
- fCachedDocument= provider.getDocument(fEditor.getEditorInput());
- fAllowCollapsing= false;
-
- Map additions= new HashMap();
- List deletions= new ArrayList();
- List updates= new ArrayList();
-
- Map updated= computeAdditions((IParent) fInput);
- Map previous= createAnnotationMap(model);
-
-
- Iterator e= updated.keySet().iterator();
- while (e.hasNext()) {
- JavaProjectionAnnotation annotation= (JavaProjectionAnnotation) e.next();
- IJavaElement element= annotation.getElement();
- Position position= (Position) updated.get(annotation);
-
- List annotations= (List) previous.get(element);
- if (annotations == null) {
-
- additions.put(annotation, position);
-
- } else {
-
- Iterator x= annotations.iterator();
- while (x.hasNext()) {
- JavaProjectionAnnotation a= (JavaProjectionAnnotation) x.next();
- if (annotation.isComment() == a.isComment()) {
- Position p= model.getPosition(a);
- if (p != null && !position.equals(p)) {
- p.setOffset(position.getOffset());
- p.setLength(position.getLength());
- updates.add(a);
- }
- x.remove();
- break;
- }
- }
-
- if (annotations.isEmpty())
- previous.remove(element);
- }
- }
-
- e= previous.values().iterator();
- while (e.hasNext()) {
- List list= (List) e.next();
- int size= list.size();
- for (int i= 0; i < size; i++)
- deletions.add(list.get(i));
- }
-
- match(model, deletions, additions, updates);
-
- Annotation[] removals= new Annotation[deletions.size()];
- deletions.toArray(removals);
- Annotation[] changes= new Annotation[updates.size()];
- updates.toArray(changes);
- model.modifyAnnotations(removals, additions, changes);
-
- } finally {
- fCachedDocument= null;
- fAllowCollapsing= true;
- }
- }
-
- private void match(ProjectionAnnotationModel model, List deletions, Map additions, List changes) {
- if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty()))
- return;
-
- List newDeletions= new ArrayList();
- List newChanges= new ArrayList();
-
- Iterator deletionIterator= deletions.iterator();
- outer: while (deletionIterator.hasNext()) {
- JavaProjectionAnnotation deleted= (JavaProjectionAnnotation) deletionIterator.next();
- Position deletedPosition= model.getPosition(deleted);
- if (deletedPosition == null)
- continue;
-
- Iterator changesIterator= changes.iterator();
- while (changesIterator.hasNext()) {
- JavaProjectionAnnotation changed= (JavaProjectionAnnotation) changesIterator.next();
- if (deleted.isComment() == changed.isComment()) {
- Position changedPosition= model.getPosition(changed);
- if (changedPosition == null)
- continue;
-
- if (deletedPosition.getOffset() == changedPosition.getOffset()) {
-
- deletedPosition.setLength(changedPosition.getLength());
- deleted.setElement(changed.getElement());
-
- deletionIterator.remove();
- newChanges.add(deleted);
-
- changesIterator.remove();
- newDeletions.add(changed);
-
- continue outer;
- }
- }
- }
-
- Iterator additionsIterator= additions.keySet().iterator();
- while (additionsIterator.hasNext()) {
- JavaProjectionAnnotation added= (JavaProjectionAnnotation) additionsIterator.next();
- if (deleted.isComment() == added.isComment()) {
- Position addedPosition= (Position) additions.get(added);
-
- if (deletedPosition.getOffset() == addedPosition.getOffset()) {
-
- deletedPosition.setLength(addedPosition.getLength());
- deleted.setElement(added.getElement());
-
- deletionIterator.remove();
- newChanges.add(deleted);
-
- additionsIterator.remove();
-
- break;
- }
- }
- }
- }
-
- deletions.addAll(newDeletions);
- changes.addAll(newChanges);
- }
-
- private Map createAnnotationMap(IAnnotationModel model) {
- Map map= new HashMap();
- Iterator e= model.getAnnotationIterator();
- while (e.hasNext()) {
- Object annotation= e.next();
- if (annotation instanceof JavaProjectionAnnotation) {
- JavaProjectionAnnotation java= (JavaProjectionAnnotation) annotation;
- List list= (List) map.get(java.getElement());
- if (list == null) {
- list= new ArrayList(2);
- map.put(java.getElement(), list);
- }
- list.add(java);
- }
- }
- return map;
- }
-}