blob: 1abb5469772633369de73eef68f365c514c89ef1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 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.jdt.internal.formatter.comment;
import java.util.LinkedList;
/**
* General comment line in a comment region.
*
* @since 3.0
*/
public abstract class CommentLine implements IBorderAttributes {
/** Prefix of non-formattable comment lines */
protected static final String NON_FORMAT_START_PREFIX= "/*-"; //$NON-NLS-1$
/** The attributes of this line */
private int fAttributes= 0;
/** The parent region of this line */
private final CommentRegion fParent;
/** The comment ranges in this line */
private final LinkedList fRanges= new LinkedList();
/**
* Creates a new comment line.
*
* @param parent comment region to create the comment line for
*/
protected CommentLine(final CommentRegion parent) {
fParent= parent;
}
/**
* Adapts the line attributes from the previous line in the comment
* region.
*
* @param previous the previous comment line in the comment region
*/
protected abstract void adapt(final CommentLine previous);
/**
* Appends the specified comment range to this comment line.
*
* @param range comment range to append to this line
*/
protected void append(final CommentRange range) {
fRanges.add(range);
}
/**
* Formats this comment line as content line.
*
* @param predecessor the predecessor comment line in the comment region
* @param last the most recently processed comment range
* @param indentation the indentation of the comment region
* @param line the index of this comment line in the comment region
* @return the first comment range in this comment line
*/
protected CommentRange formatLine(final CommentLine predecessor, final CommentRange last, final String indentation, final int line) {
int offset= 0;
int length= 0;
CommentRange next= last;
CommentRange previous= null;
final int stop= fRanges.size() - 1;
final int end= fParent.getSize() - 1;
for (int index= stop; index >= 0; index--) {
previous= next;
next= (CommentRange)fRanges.get(index);
if (fParent.canFormat(previous, next)) {
offset= next.getOffset() + next.getLength();
length= previous.getOffset() - offset;
if (index == stop && line != end)
fParent.logEdit(fParent.getDelimiter(predecessor, this, previous, next, indentation), offset, length);
else
fParent.logEdit(fParent.getDelimiter(previous, next), offset, length);
}
}
return next;
}
/**
* Formats this comment line as end line having a lower border
* consisting of content line prefixes.
*
* @param range last comment range of the last comment line in the
* comment region
* @param indentation the indentation of the comment region
* @param length the maximal length of text in this comment region
* measured in average character widths
*/
protected void formatLowerBorder(final CommentRange range, final String indentation, final int length) {
final int offset= range.getOffset() + range.getLength();
final StringBuffer buffer= new StringBuffer(length);
final String end= getEndingPrefix();
final String delimiter= fParent.getDelimiter();
if (fParent.isSingleLine() && fParent.getSize() == 1)
buffer.append(end);
else {
final String filler= getContentPrefix().trim();
buffer.append(delimiter);
buffer.append(indentation);
if (fParent.hasBorder(BORDER_LOWER)) {
buffer.append(' ');
for (int character= 0; character < length; character++)
buffer.append(filler);
buffer.append(end.trim());
} else
buffer.append(end);
}
fParent.logEdit(buffer.toString(), offset, fParent.getLength() - offset);
}
/**
* Formats this comment line as start line having an upper border
* consisting of content line prefixes.
*
* @param range the first comment range in the comment region
* @param indentation the indentation of the comment region
* @param length the maximal length of text in this comment region
* measured in average character widths
*/
protected void formatUpperBorder(final CommentRange range, final String indentation, final int length) {
final StringBuffer buffer= new StringBuffer(length);
final String start= getStartingPrefix();
final String content= getContentPrefix();
if (fParent.isSingleLine() && fParent.getSize() == 1)
buffer.append(start);
else {
final String trimmed= start.trim();
final String filler= content.trim();
buffer.append(trimmed);
if (fParent.hasBorder(BORDER_UPPER)) {
for (int character= 0; character < length - trimmed.length() + start.length(); character++)
buffer.append(filler);
}
buffer.append(fParent.getDelimiter());
buffer.append(indentation);
buffer.append(content);
}
fParent.logEdit(buffer.toString(), 0, range.getOffset());
}
/**
* Returns the line prefix of content lines.
*
* @return line prefix of content lines
*/
protected abstract String getContentPrefix();
/**
* Returns the line prefix of end lines.
*
* @return line prefix of end lines
*/
protected abstract String getEndingPrefix();
/**
* Returns the first comment range in this comment line.
*
* @return the first comment range
*/
protected final CommentRange getFirst() {
return (CommentRange)fRanges.getFirst();
}
/**
* Returns the indentation reference string for this line.
*
* @return the indentation reference string for this line
*/
protected String getIndentationReference() {
return ""; //$NON-NLS-1$
}
/**
* Returns the last comment range in this comment line.
*
* @return the last comment range
*/
protected final CommentRange getLast() {
return (CommentRange)fRanges.getLast();
}
/**
* Returns the parent comment region of this comment line.
*
* @return the parent comment region
*/
protected final CommentRegion getParent() {
return fParent;
}
/**
* Returns the number of comment ranges in this comment line.
*
* @return the number of ranges in this line
*/
protected final int getSize() {
return fRanges.size();
}
/**
* Returns the line prefix of start lines.
*
* @return line prefix of start lines
*/
protected abstract String getStartingPrefix();
/**
* Is the attribute <code>attribute</code> true?
*
* @param attribute the attribute to get.
* @return <code>true</code> iff this attribute is <code>true</code>,
* <code>false</code> otherwise.
*/
protected final boolean hasAttribute(final int attribute) {
return (fAttributes & attribute) == attribute;
}
/**
* Scans this comment line for comment range boundaries.
*
* @param line the index of this line in the comment region
*/
protected abstract void scanLine(final int line);
/**
* Set the attribute <code>attribute</code> to true.
*
* @param attribute the attribute to set.
*/
protected final void setAttribute(final int attribute) {
fAttributes |= attribute;
}
/**
* Tokenizes this comment line into comment ranges
*
* @param line the index of this line in the comment region
*/
protected void tokenizeLine(final int line) {
int offset= 0;
int index= offset;
final CommentRange range= (CommentRange)fRanges.get(0);
final int begin= range.getOffset();
final String content= fParent.getText(begin, range.getLength());
final int length= content.length();
while (offset < length) {
while (offset < length && Character.isWhitespace(content.charAt(offset)))
offset++;
index= offset;
while (index < length && !Character.isWhitespace(content.charAt(index)))
index++;
if (index - offset > 0) {
fParent.append(new CommentRange(begin + offset, index - offset));
offset= index;
}
}
}
}