📄 abstractifdirective.java
字号:
/**
* Copyright (c) 2003-2005 Craig Setera
* All Rights Reserved.
* Licensed under the Eclipse Public License - v 1.0
* For more information see http://www.eclipse.org/legal/epl-v10.html
*/
package eclipseme.core.internal.preprocessor.directive;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.dom.Comment;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import eclipseme.core.internal.EclipseMECorePlugin;
import eclipseme.core.internal.preprocessor.Directive;
import eclipseme.core.internal.preprocessor.ProcessingState;
import eclipseme.core.model.SymbolDefinitionSet;
/**
* Abstract superclass of all if conditional directives.
* If directives define a set of conditional blocks that
* are or are not enabled.
* <p />
* Copyright (c) 2003-2005 Craig Setera<br>
* All Rights Reserved.<br>
* Licensed under the Eclipse Public License - v 1.0<p/>
* <br>
* $Revision: 1.3 $
* <br>
* $Date: 2006/11/19 01:37:59 $
* <br>
* @author Craig Setera
*/
public abstract class AbstractIfDirective extends AbstractStartDirective {
private static final String LINE_COMMENT = "//# ";
protected class ConditionalBlock {
private Directive[] directives;
/**
* Construct a new instance.
*
* @param directives
*/
public ConditionalBlock(Directive[] directives) {
this.directives = directives;
}
/**
* Return the directives that are part of this block.
*
* @return
*/
public Directive[] getDirectives() {
return directives;
}
/**
* @return Returns the endDirective.
*/
public Directive getEndDirective() {
return directives[directives.length - 1];
}
/**
* Return the region covered by this conditional block.
*
* @return
* @throws CoreException
*/
public IRegion getRegion()
throws CoreException
{
IRegion startRegion = getStartDirective().getRegion();
IRegion endRegion = getEndDirective().getRegion();
int length =
(endRegion.getOffset() - startRegion.getOffset()) +
endRegion.getLength();
return new Region(startRegion.getOffset(), length);
}
/**
* @return Returns the startDirective.
*/
public Directive getStartDirective() {
return directives[0];
}
/**
* Return a boolean indicating whether the specified block
* should be enabled.
*
* @param identifiers
* @param monitor
* @return
*/
public boolean isEnabled(SymbolDefinitionSet identifiers, IProgressMonitor monitor) {
AbstractConditionalDirective startDirective =
(AbstractConditionalDirective) getStartDirective();
return startDirective.isEnabled(identifiers, monitor);
}
}
private ConditionalBlock[] conditionalBlocks;
/**
* Construct a new instance.
*
* @param compilationUnit
* @param comment
* @param commentText
*/
public AbstractIfDirective(
IResource resource,
Comment comment,
String commentText)
{
super(resource, comment, commentText);
}
/**
* @see eclipseme.core.internal.preprocessor.Directive#execute(ProcessingState, IProgressMonitor)
*/
public void execute(ProcessingState processingState, IProgressMonitor monitor)
throws CoreException
{
if (isValid()) {
ConditionalBlock[] blocks = getConditionalBlocks();
int enabledBlock = findEnabledBlock(blocks, processingState.symbols, monitor);
for (int i = 0; i < blocks.length; i++) {
if (i == enabledBlock) {
Directive[] children = blocks[i].getDirectives();
for (int j = 1; j < children.length - 1; j++) {
children[j].execute(processingState, monitor);
}
} else {
disableBlock(processingState, blocks[i]);
}
}
}
}
/**
* Disable the code in the document based on the
* conditional block.
*
* @param processingState
* @param block
* @throws CoreException
* @throws BadLocationException
*/
protected void disableBlock(ProcessingState processingState, ConditionalBlock block)
throws CoreException
{
IDocument document = processingState.document;
IRegion blockRegion = block.getRegion();
int startLine = getLineOfOffset(processingState, blockRegion.getOffset());
int endLine = getLineOfOffset(
processingState,
blockRegion.getOffset() + blockRegion.getLength());
for (int line = startLine + 1; line < endLine; line++) {
try {
int lineOffset = document.getLineOffset(line);
insertText(processingState, lineOffset, LINE_COMMENT);
} catch (BadLocationException e) {
EclipseMECorePlugin.throwCoreException(IStatus.ERROR, -999, e);
}
}
}
/**
* Find and return the first enabled block in the list of
* blocks.
*
* @param blocks
* @param symbols
* @param monitor
* @return
*/
private int findEnabledBlock(
ConditionalBlock[] blocks,
SymbolDefinitionSet symbols,
IProgressMonitor monitor)
{
int blockIndex = -1;
for (int i = 0; i < blocks.length; i++) {
ConditionalBlock block = blocks[i];
if (block.isEnabled(symbols, monitor)) {
blockIndex = i;
break;
}
}
return blockIndex;
}
/**
* Return an array of conditional blocks.
*
* @return
*/
protected ConditionalBlock[] getConditionalBlocks() {
if (conditionalBlocks == null) {
ArrayList blocks = new ArrayList();
ArrayList blockDirectives = new ArrayList();
blockDirectives.add(this);
Iterator iterator = children.iterator();
while (iterator.hasNext()) {
Directive directive = (Directive) iterator.next();
blockDirectives.add(directive);
if (directive.isConditionalDirective()) {
AbstractConditionalDirective conditional =
(AbstractConditionalDirective) directive;
if (conditional.isElseDirective() || conditional.isContainerEnd()) {
ConditionalBlock block = new ConditionalBlock(
(Directive[]) blockDirectives.toArray(new Directive[blockDirectives.size()]));
blocks.add(block);
blockDirectives.clear();
blockDirectives.add(directive);
}
}
}
conditionalBlocks =
(ConditionalBlock[]) blocks.toArray(new ConditionalBlock[blocks.size()]);
}
return conditionalBlocks;
}
/**
* Return a boolean indicating whether or not this directive is
* currently valid.
*
* @return
* @throws CoreException
*/
protected abstract boolean isValid() throws CoreException;
/**
* Validate the specific child directive. Return a boolean indicating
* whether the directive is valid within this if directive and add
* a problem marker if it is not valid.
*
* @param directive
* @return
* @throws CoreException
*/
protected abstract boolean validateChild(Directive directive) throws CoreException;
/**
* Validate the children of this directive, returning a boolean
* indicating the validity.
*
* @return
* @throws CoreException
*/
protected boolean validateChildren()
throws CoreException
{
boolean valid = true;
Directive[] children = getChildren();
for (int i = 0; i < children.length && valid; i++) {
Directive directive = children[i];
valid = validateChild(directive);
}
if (valid) {
valid = validateClosed();
}
return valid;
}
/**
* Validate that the if directive is appropriately closed.
*
* @return
* @throws CoreException
*/
private boolean validateClosed()
throws CoreException
{
boolean closed = false;
Directive[] children = getChildren();
if (children.length > 0) {
Directive lastChild = children[children.length - 1];
closed = lastChild.isConditionalDirective() && lastChild.isContainerEnd();
}
if (!closed) {
createProblemMarker(IMarker.SEVERITY_ERROR, "Conditional directive not closed");
}
return closed;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -