X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java b/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java deleted file mode 100644 index ddac268..0000000 --- a/net.sourceforge.phpeclipse.ui/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java +++ /dev/null @@ -1,1064 +0,0 @@ -/******************************************************************************* - * 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.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import net.sourceforge.phpdt.core.ElementChangedEvent; -import net.sourceforge.phpdt.core.ICompilationUnit; -import net.sourceforge.phpdt.core.IElementChangedListener; -import net.sourceforge.phpdt.core.IJavaElement; -import net.sourceforge.phpdt.core.IJavaElementDelta; -import net.sourceforge.phpdt.core.IMember; -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.internal.compiler.parser.Scanner; -import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator; -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 net.sourceforge.phpeclipse.ui.WebUI; - -import org.eclipse.jface.preference.IPreferenceStore; -//incastrix -//import org.eclipse.jface.text.Assert; -import org.eclipse.core.runtime.Assert; -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.IProjectionPosition; -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; - } - - /* - * @see java.lang.Object#toString() - */ - public String toString() { - return "JavaProjectionAnnotation:\n" + //$NON-NLS-1$ - "\telement: \t" + fJavaElement.toString() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ - "\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ - "\tcomment: \t" + fIsComment + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ - } - } - - private static final class Tuple { - JavaProjectionAnnotation annotation; - - Position position; - - Tuple(JavaProjectionAnnotation annotation, Position position) { - this.annotation = annotation; - this.position = position; - } - } - - private class ElementChangedListener implements IElementChangedListener { - - /* - * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.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(); - - for (int i = 0; i < children.length; i++) { - IJavaElementDelta d = findElement(target, children[i]); - if (d != null) - return d; - } - - return null; - } - } - - /** - * Projection position that will return two foldable regions: one folding - * away the region from after the '/**' to the beginning of the content, the - * other from after the first content line until after the comment. - * - * @since 3.1 - */ - private static final class CommentPosition extends Position implements - IProjectionPosition { - CommentPosition(int offset, int length) { - super(offset, length); - } - - /* - * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument) - */ - public IRegion[] computeProjectionRegions(IDocument document) - throws BadLocationException { - DocumentCharacterIterator sequence = new DocumentCharacterIterator( - document, offset, offset + length); - int prefixEnd = 0; - int contentStart = findFirstContent(sequence, prefixEnd); - - int firstLine = document.getLineOfOffset(offset + prefixEnd); - int captionLine = document.getLineOfOffset(offset + contentStart); - int lastLine = document.getLineOfOffset(offset + length); - - Assert.isTrue(firstLine <= captionLine, - "first folded line is greater than the caption line"); //$NON-NLS-1$ - Assert.isTrue(captionLine <= lastLine, - "caption line is greater than the last folded line"); //$NON-NLS-1$ - - IRegion preRegion; - if (firstLine < captionLine) { - // preRegion= new Region(offset + prefixEnd, contentStart - - // prefixEnd); - int preOffset = document.getLineOffset(firstLine); - IRegion preEndLineInfo = document - .getLineInformation(captionLine); - int preEnd = preEndLineInfo.getOffset(); - preRegion = new Region(preOffset, preEnd - preOffset); - } else { - preRegion = null; - } - - if (captionLine < lastLine) { - int postOffset = document.getLineOffset(captionLine + 1); - IRegion postRegion = new Region(postOffset, offset + length - - postOffset); - - if (preRegion == null) - return new IRegion[] { postRegion }; - - return new IRegion[] { preRegion, postRegion }; - } - - if (preRegion != null) - return new IRegion[] { preRegion }; - - return null; - } - - /** - * Finds the offset of the first identifier part within - * content. Returns 0 if none is found. - * - * @param content - * the content to search - * @return the first index of a unicode identifier part, or zero if none - * can be found - */ - private int findFirstContent(final CharSequence content, int prefixEnd) { - int lenght = content.length(); - for (int i = prefixEnd; i < lenght; i++) { - if (Character.isUnicodeIdentifierPart(content.charAt(i))) - return i; - } - return 0; - } - - // /** - // * Finds the offset of the first identifier part within - // content. - // * Returns 0 if none is found. - // * - // * @param content the content to search - // * @return the first index of a unicode identifier part, or zero if - // none - // can - // * be found - // */ - // private int findPrefixEnd(final CharSequence content) { - // // return the index after the leading '/*' or '/**' - // int len= content.length(); - // int i= 0; - // while (i < len && isWhiteSpace(content.charAt(i))) - // i++; - // if (len >= i + 2 && content.charAt(i) == '/' && content.charAt(i + 1) - // == - // '*') - // if (len >= i + 3 && content.charAt(i + 2) == '*') - // return i + 3; - // else - // return i + 2; - // else - // return i; - // } - // - // private boolean isWhiteSpace(char c) { - // return c == ' ' || c == '\t'; - // } - - /* - * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument) - */ - public int computeCaptionOffset(IDocument document) { - // return 0; - DocumentCharacterIterator sequence = new DocumentCharacterIterator( - document, offset, offset + length); - return findFirstContent(sequence, 0); - } - } - - /** - * Projection position that will return two foldable regions: one folding - * away the lines before the one containing the simple name of the java - * element, one folding away any lines after the caption. - * - * @since 3.1 - */ - private static final class JavaElementPosition extends Position implements - IProjectionPosition { - - private IMember fMember; - - public JavaElementPosition(int offset, int length, IMember member) { - super(offset, length); - Assert.isNotNull(member); - fMember = member; - } - - public void setMember(IMember member) { - Assert.isNotNull(member); - fMember = member; - } - - /* - * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument) - */ - public IRegion[] computeProjectionRegions(IDocument document) - throws BadLocationException { - int nameStart = offset; - try { - /* - * The member's name range may not be correct. However, - * reconciling would trigger another element delta which would - * lead to reentrant situations. Therefore, we optimistically - * assume that the name range is correct, but double check the - * received lines below. - */ - ISourceRange nameRange = fMember.getNameRange(); - if (nameRange != null) - nameStart = nameRange.getOffset(); - - } catch (JavaModelException e) { - // ignore and use default - } - - int firstLine = document.getLineOfOffset(offset); - int captionLine = document.getLineOfOffset(nameStart); - int lastLine = document.getLineOfOffset(offset + length); - - /* - * see comment above - adjust the caption line to be inside the - * entire folded region, and rely on later element deltas to correct - * the name range. - */ - if (captionLine < firstLine) - captionLine = firstLine; - if (captionLine > lastLine) - captionLine = lastLine; - - IRegion preRegion; - if (firstLine < captionLine) { - int preOffset = document.getLineOffset(firstLine); - IRegion preEndLineInfo = document - .getLineInformation(captionLine); - int preEnd = preEndLineInfo.getOffset(); - preRegion = new Region(preOffset, preEnd - preOffset); - } else { - preRegion = null; - } - - if (captionLine < lastLine) { - int postOffset = document.getLineOffset(captionLine + 1); - IRegion postRegion = new Region(postOffset, offset + length - - postOffset); - - if (preRegion == null) - return new IRegion[] { postRegion }; - - return new IRegion[] { preRegion, postRegion }; - } - - if (preRegion != null) - return new IRegion[] { preRegion }; - - return null; - } - - /* - * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument) - */ - public int computeCaptionOffset(IDocument document) - throws BadLocationException { - int nameStart = offset; - try { - // need a reconcile here? - ISourceRange nameRange = fMember.getNameRange(); - if (nameRange != null) - nameStart = nameRange.getOffset(); - } catch (JavaModelException e) { - // ignore and use default - } - - return nameStart - offset; - } - - } - - private IDocument fCachedDocument; - - private ProjectionAnnotationModel fCachedModel; - - 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; - - private boolean fCollapseHeaderComments = true; - - /* caches for header comment extraction. */ - private IType fFirstType; - - private boolean fHasHeaderComment; - - 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() { - // http://home.ott.oti.com/teams/wswb/anon/out/vms/index.html - // projectionEnabled messages are not always paired with - // projectionDisabled - // i.e. multiple enabled messages may be sent out. - // we have to make sure that we disable first when getting an enable - // message. - projectionDisabled(); - - 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; - - fFirstType = null; - fHasHeaderComment = false; - - if (fEditor instanceof PHPUnitEditor) { - IWorkingCopyManager manager = WebUI.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) { - fCachedModel = model; - if (fInput instanceof ICompilationUnit) { - ICompilationUnit unit = (ICompilationUnit) fInput; - synchronized (unit) { - try { - // unit.reconcile(ICompilationUnit.NO_AST, - // false, null, null); - unit.reconcile(); - } catch (JavaModelException x) { - } - } - } - - Map additions = computeAdditions((IParent) fInput); - /* - * Minimize the events being sent out - as this happens in - * the UI thread merge everything into one call. - */ - List removals = new LinkedList(); - Iterator existing = model.getAnnotationIterator(); - while (existing.hasNext()) - removals.add(existing.next()); - model.replaceAnnotations((Annotation[]) removals - .toArray(new Annotation[removals.size()]), - additions); - } - } - - } finally { - fCachedDocument = null; - fCachedModel = null; - fAllowCollapsing = false; - - fFirstType = null; - fHasHeaderComment = false; - } - } - - private void initializePreferences() { - IPreferenceStore store = WebUI.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); - fCollapseHeaderComments = store - .getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS); - } - - private Map computeAdditions(IParent parent) { - Map map = new LinkedHashMap(); // use a linked map to maintain ordering - // of - // comments - 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; - if (isInnerType((IType) element)) { - collapse = collapse && fCollapseInnerTypes; - } else { - collapse = false; // don't allow the most outer type to be - // folded, may be changed in future versions - } - 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], - null); - boolean commentCollapse; - if (position != null) { - if (i == 0 && (regions.length > 2 || fHasHeaderComment) - && element == fFirstType) { - commentCollapse = fAllowCollapsing - && fCollapseHeaderComments; - } else { - commentCollapse = fAllowCollapsing - && fCollapseJavadoc; - } - map.put(new JavaProjectionAnnotation(element, - commentCollapse, true), position); - } - } - // code - Position position = createProjectionPosition( - regions[regions.length - 1], element); - 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; - } - - /** - * Computes the projection ranges for a given IJavaElement. - * More than one range may be returned if the element has a leading comment - * which gets folded separately. If there are no foldable regions, - * null is returned. - * - * @param element - * the java element that can be folded - * @return the regions to be folded, or null if there are - * none - */ - 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; - - List regions = new ArrayList(); - // now add all comments first to the regions list - if (fFirstType == null && element instanceof IType) { - fFirstType = (IType) element; - IRegion headerComment = computeHeaderComment(fFirstType); - if (headerComment != null) { - regions.add(headerComment); - fHasHeaderComment = true; - } - } - - final int shift = range.getOffset(); - int start = shift; - if (element instanceof IType) { - Scanner scanner = ToolFactory.createScanner(true, false, - false, false); - scanner.setSource(contents.toCharArray()); - scanner.setPHPMode(true); - - int token = scanner.getNextToken(); - while (token != ITerminalSymbols.TokenNameEOF) { - - token = scanner.getNextToken(); - start = shift + scanner.getCurrentTokenStartPosition(); - - switch (token) { - case ITerminalSymbols.TokenNameCOMMENT_PHPDOC: - case ITerminalSymbols.TokenNameCOMMENT_BLOCK: { - int end = shift - + scanner.getCurrentTokenEndPosition() + 1; - regions.add(new Region(start, end - start)); - } - case ITerminalSymbols.TokenNameCOMMENT_LINE: - continue; - } - } - } - // at the end add the element region - regions.add(new Region(range.getOffset(), range.getLength())); - - if (regions.size() > 0) { - IRegion[] result = new IRegion[regions.size()]; - regions.toArray(result); - return result; - } - - } - } catch (JavaModelException e) { - } catch (InvalidInputException e) { - } - - return null; - } - - private IRegion computeHeaderComment(IType type) throws JavaModelException { - if (fCachedDocument == null) - return null; - - // search at most up to the first type - ISourceRange range = type.getSourceRange(); - if (range == null) - return null; - int start = 0; - int end = range.getOffset(); - - if (fInput instanceof ISourceReference) { - String content; - try { - content = fCachedDocument.get(start, end - start); - } catch (BadLocationException e) { - return null; // ignore header comment in that case - } - - /* - * code adapted from CommentFormattingStrategy: scan the header - * content up to the first type. Once a comment is found, accumulate - * any additional comments up to the stop condition. The stop - * condition is reaching a package declaration, import container, or - * the end of the input. - */ - IScanner scanner = ToolFactory.createScanner(true, false, false, - false); - scanner.setSource(content.toCharArray()); - - int headerStart = -1; - int headerEnd = -1; - try { - boolean foundComment = false; - int terminal = scanner.getNextToken(); - while (terminal != ITerminalSymbols.TokenNameEOF - && !(terminal == ITerminalSymbols.TokenNameclass - || terminal == ITerminalSymbols.TokenNameinterface || foundComment)) { - - if (terminal == ITerminalSymbols.TokenNameCOMMENT_PHPDOC - || terminal == ITerminalSymbols.TokenNameCOMMENT_BLOCK - || terminal == ITerminalSymbols.TokenNameCOMMENT_LINE) { - if (!foundComment) - headerStart = scanner - .getCurrentTokenStartPosition(); - headerEnd = scanner.getCurrentTokenEndPosition(); - foundComment = true; - } - terminal = scanner.getNextToken(); - } - - } catch (InvalidInputException ex) { - return null; - } - - if (headerEnd != -1) { - return new Region(headerStart, headerEnd - headerStart); - } - } - return null; - } - - private Position createProjectionPosition(IRegion region, - IJavaElement element) { - - 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; - if (fCachedDocument.getNumberOfLines() > end + 1) - endOffset = fCachedDocument.getLineOffset(end + 1); - else if (end > start) - endOffset = fCachedDocument.getLineOffset(end) - + fCachedDocument.getLineLength(end); - else - return null; - if (element instanceof IMember) - return new JavaElementPosition(offset, endOffset - offset, - (IMember) element); - else - return new CommentPosition(offset, endOffset - offset); - } - - } catch (BadLocationException x) { - } - - return null; - } - - protected void processDelta(IJavaElementDelta delta) { - - if (!isInstalled()) - return; - - if ((delta.getFlags() & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_CHILDREN)) == 0) - return; - - ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor - .getAdapter(ProjectionAnnotationModel.class); - if (model == null) - return; - - try { - - IDocumentProvider provider = fEditor.getDocumentProvider(); - fCachedDocument = provider.getDocument(fEditor.getEditorInput()); - fCachedModel = model; - fAllowCollapsing = false; - - fFirstType = null; - fHasHeaderComment = 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 newAnnotation = (JavaProjectionAnnotation) e - .next(); -//+ - Position newPosition = (Position) updated.get(newAnnotation); - additions.put(newAnnotation, newPosition); -//- -// IJavaElement element = newAnnotation.getElement(); -// Position newPosition = (Position) updated.get(newAnnotation); -// -// List annotations = (List) previous.get(element); -// if (annotations == null) { -// -// additions.put(newAnnotation, newPosition); -// -// } else { -// Iterator x = annotations.iterator(); -// boolean matched = false; -// while (x.hasNext()) { -// Tuple tuple = (Tuple) x.next(); -// JavaProjectionAnnotation existingAnnotation = tuple.annotation; -// Position existingPosition = tuple.position; -// if (newAnnotation.isComment() == existingAnnotation -// .isComment()) { -// if (existingPosition != null -// && (!newPosition.equals(existingPosition))) { -// existingPosition.setOffset(newPosition -// .getOffset()); -// existingPosition.setLength(newPosition -// .getLength()); -// updates.add(existingAnnotation); -// } -// matched = true; -// x.remove(); -// break; -// } -// } -// if (!matched) -// additions.put(newAnnotation, newPosition); -// -// 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(((Tuple) list.get(i)).annotation); - } - - match(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; - fCachedModel = null; - - fFirstType = null; - fHasHeaderComment = false; - } - } - - /** - * Matches deleted annotations to changed or added ones. A deleted - * annotation/position tuple that has a matching addition / change is - * updated and marked as changed. The matching tuple is not added (for - * additions) or marked as deletion instead (for changes). The result is - * that more annotations are changed and fewer get deleted/re-added. - */ - private void match(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(); - while (deletionIterator.hasNext()) { - JavaProjectionAnnotation deleted = (JavaProjectionAnnotation) deletionIterator - .next(); - Position deletedPosition = fCachedModel.getPosition(deleted); - if (deletedPosition == null) - continue; - - Tuple deletedTuple = new Tuple(deleted, deletedPosition); - - Tuple match = findMatch(deletedTuple, changes, null); - boolean addToDeletions = true; - if (match == null) { - match = findMatch(deletedTuple, additions.keySet(), additions); - addToDeletions = false; - } - - if (match != null) { - IJavaElement element = match.annotation.getElement(); - deleted.setElement(element); - deletedPosition.setLength(match.position.getLength()); - if (deletedPosition instanceof JavaElementPosition - && element instanceof IMember) { - JavaElementPosition jep = (JavaElementPosition) deletedPosition; - jep.setMember((IMember) element); - } - - deletionIterator.remove(); - newChanges.add(deleted); - - if (addToDeletions) - newDeletions.add(match.annotation); - } - } - - deletions.addAll(newDeletions); - changes.addAll(newChanges); - } - - /** - * Finds a match for tuple in a collection of annotations. - * The positions for the JavaProjectionAnnotation instances - * in annotations can be found in the passed - * positionMap or fCachedModel if - * positionMap is null. - *

- * A tuple is said to match another if their annotations have the same - * comment flag and their position offsets are equal. - *

- *

- * If a match is found, the annotation gets removed from - * annotations. - *

- * - * @param tuple - * the tuple for which we want to find a match - * @param annotations - * collection of JavaProjectionAnnotation - * @param positionMap - * a Map<Annotation, Position> or - * null - * @return a matching tuple or null for no match - */ - private Tuple findMatch(Tuple tuple, Collection annotations, Map positionMap) { - Iterator it = annotations.iterator(); - while (it.hasNext()) { - JavaProjectionAnnotation annotation = (JavaProjectionAnnotation) it - .next(); - if (tuple.annotation.isComment() == annotation.isComment()) { - Position position = positionMap == null ? fCachedModel - .getPosition(annotation) : (Position) positionMap - .get(annotation); - if (position == null) - continue; - - if (tuple.position.getOffset() == position.getOffset()) { - it.remove(); - return new Tuple(annotation, position); - } - } - } - - return null; - } - - 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; - Position position = model.getPosition(java); - Assert.isNotNull(position); - List list = (List) map.get(java.getElement()); - if (list == null) { - list = new ArrayList(2); - map.put(java.getElement(), list); - } - list.add(new Tuple(java, position)); - } - } - - Comparator comparator = new Comparator() { - public int compare(Object o1, Object o2) { - return ((Tuple) o1).position.getOffset() - - ((Tuple) o2).position.getOffset(); - } - }; - for (Iterator it = map.values().iterator(); it.hasNext();) { - List list = (List) it.next(); - Collections.sort(list, comparator); - } - return map; - } -} \ No newline at end of file