/******************************************************************************* * Copyright (c) 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.sse.ui.internal.comment; import java.util.List; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.Region; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; import org.eclipse.wst.sse.ui.internal.Logger; /** * <p>Represents a Block Comment commenting strategy</p> */ public class BlockCommentingStrategy extends CommentingStrategy { /** the prefix of the block comment associated with this strategy */ private String fPrefix; /** the suffix of the block comment associated with this strategy */ private String fSuffix; /** * @param prefix the prefix of the block comment associated with this strategy * @param suffix the suffix of the block comment associated with this strategy */ public BlockCommentingStrategy(String prefix, String suffix) { super(); this.fPrefix = prefix; this.fSuffix = suffix; } /** * <p>When applying a block comment it also removes any block comments associated * with this strategy that would now be enclosed by the new block comment</p> * * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#apply( * org.eclipse.wst.sse.core.internal.provisional.IStructuredModel, int, int) */ public void apply(IStructuredDocument document, int offset, int length) throws BadLocationException { int commentPrefixOffset = offset; int commentSuffixOffset = commentPrefixOffset + length; try { document.replace(commentSuffixOffset, 0, " " + this.fSuffix); //$NON-NLS-1$ this.remove(document, commentPrefixOffset + this.fPrefix.length(), length, false); document.replace(commentPrefixOffset, 0, this.fPrefix + " "); //$NON-NLS-1$ } catch (BadLocationException e) { Logger.log(Logger.WARNING_DEBUG, e.getMessage(), e); } } /** * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#remove( * org.eclipse.jface.text.IDocument, int, int) */ public void remove(IStructuredDocument document, int offset, int length, boolean removeEnclosing) throws BadLocationException { IRegion region = new Region(offset, length); ITypedRegion[] typedRegions = document.computePartitioning(region.getOffset(), region.getLength()); List commentRegions = this.getAssociatedCommentedRegions(typedRegions); //remove in reverse order as to not effect offset of other regions for(int i = commentRegions.size()-1; i >= 0; --i) { try { //get the comment region ITypedRegion typedRegion = (ITypedRegion)commentRegions.get(i); IRegion commentRegion = new Region(typedRegion.getOffset(), typedRegion.getLength()); /* because of the nature of structured regions the comment region could actually be a * sub region that needs to be drilled down too */ if(!this.alreadyCommenting(document, commentRegion)) { IStructuredDocumentRegion structuredRegion = document.getRegionAtCharacterOffset(commentRegion.getOffset()); commentRegion = new Region(structuredRegion.getStartOffset(), structuredRegion.getLength()); if(!this.alreadyCommenting(document, commentRegion)) { ITextRegion enclosedRegion = structuredRegion.getRegionAtCharacterOffset(typedRegion.getOffset()); int enclosedOffset = structuredRegion.getStartOffset(enclosedRegion); commentRegion = new Region(enclosedOffset, structuredRegion.getTextEndOffset(enclosedRegion)-enclosedOffset); } } //at this point should have found the comment region, if not there is an issue if(this.alreadyCommenting(document, commentRegion)) { String regionContent = document.get(commentRegion.getOffset(), commentRegion.getLength()); //if found the comment prefix and suffix then uncomment, otherwise log error int commentPrefixOffset = commentRegion.getOffset() + regionContent.indexOf(this.fPrefix); int commentSuffixOffset = commentRegion.getOffset(); commentSuffixOffset += regionContent.lastIndexOf(this.fSuffix); //remove comment block depending on if its an enclosing comment block and weather that is allowed if(removeEnclosing || (commentPrefixOffset >= offset && commentSuffixOffset <= offset+length)) { uncomment(document, commentPrefixOffset, this.fPrefix, commentSuffixOffset, this.fSuffix); } } else { Logger.log(Logger.ERROR, "BlockCommentingStrategy#remove could not find the commenting region to remove"); //$NON-NLS-1$ } } catch(BadLocationException e) { Logger.logException("This should only ever happen if something has gone wrong with the partitioning", e); //$NON-NLS-1$ } } } /** * <p>A region is already commented by this strategy if it starts with the strategy's associated * prefix and ends with its associated suffix, ignoring any trailing or leading whitespace</p> * * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#alreadyCommenting( * org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IRegion) */ public boolean alreadyCommenting(IStructuredDocument document, IRegion region) throws BadLocationException { String regionContent = document.get(region.getOffset(), region.getLength()).trim(); return regionContent.startsWith(this.fPrefix) && regionContent.endsWith(this.fSuffix); } /** * @see org.eclipse.wst.sse.ui.internal.comment.CommentingStrategy#clone() */ public Object clone() { return new BlockCommentingStrategy(this.fPrefix, this.fSuffix); } }