001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.model.definitions.indent;
038:
039: import javax.swing.text.*;
040: import edu.rice.cs.util.UnexpectedException;
041:
042: import edu.rice.cs.drjava.model.AbstractDJDocument;
043: import edu.rice.cs.drjava.model.definitions.reducedmodel.*;
044:
045: /** Determines whether or not the current line in the document starts with a specific character sequence,
046: * skipping over any comments on that line. The character sequence is passed to the constructor of the class
047: * as a String argument.
048: * @version $Id: QuestionCurrLineStartsWithSkipComments.java 4255 2007-08-28 19:17:37Z mgricken $
049: */
050: public class QuestionCurrLineStartsWithSkipComments extends
051: IndentRuleQuestion {
052: /** The String to be matched. This String may not contain whitespace characters
053: * or comment-delimiting characters.
054: */
055: private String _prefix;
056:
057: /** @param yesRule The decision subtree for the case that this rule applies in the current context.
058: * @param noRule The decision subtree for the case that this rule does not apply in the current context.
059: */
060: public QuestionCurrLineStartsWithSkipComments(String prefix,
061: IndentRule yesRule, IndentRule noRule) {
062: super (yesRule, noRule);
063: _prefix = prefix;
064: }
065:
066: /** Determines whether or not the current line in the document starts
067: * with the character sequence specified by the String field _prefix,
068: * skipping over any comments on that line.
069: * @param doc The AbstractDJDocument containing the current line.
070: * @return True iff the current line in the document starts with the
071: * character sequence specified by the String field _prefix.
072: */
073: boolean applyRule(AbstractDJDocument doc,
074: Indenter.IndentReason reason) {
075: try {
076: // Find the first non-whitespace character on the current line.
077:
078: int currentPos = doc.getCurrentLocation(), startPos = doc
079: .getLineFirstCharPos(currentPos), endPos = doc
080: .getLineEndPos(currentPos), lineLength = endPos
081: - startPos;
082:
083: char currentChar, previousChar = '\0';
084: String text = doc.getText(startPos, lineLength);
085:
086: for (int i = 0; i < lineLength; i++) {
087: // Get state for walker position.
088: //BraceReduction reduced = doc.getReduced();
089:
090: doc.move(startPos - currentPos + i);
091: ReducedModelState state = doc.getStateAtCurrent();
092: doc.move(-startPos + currentPos - i);
093:
094: currentChar = text.charAt(i);
095:
096: if (state.equals(ReducedModelState.INSIDE_LINE_COMMENT))
097: return false;
098: if (state
099: .equals(ReducedModelState.INSIDE_BLOCK_COMMENT)) { // Handle case: ...*/*
100: previousChar = '\0';
101: continue;
102: }
103: if (state.equals(ReducedModelState.FREE)) { // Can prefix still fit on the current line?
104: if (_prefix.length() > lineLength - i)
105: return false;
106: else if (text.substring(i, i + _prefix.length())
107: .equals(_prefix)
108: && previousChar != '/') {
109: // '/' is the only non-WS character that we consume without
110: // immediately returning false. When we try to match the prefix,
111: // we also need to reflect this implicit lookahead mechanism.
112: return true;
113: } else if (currentChar == '/') {
114: if (previousChar == '/')
115: return false;
116: } else if (currentChar == ' '
117: || currentChar == '\t') {
118: } else if (!(currentChar == '*' && previousChar == '/'))
119: return false;
120: }
121: if (previousChar == '/' && currentChar != '*')
122: return false;
123: previousChar = currentChar;
124: }
125: return false;
126: } catch (BadLocationException e) {
127: // Control flow should never reach this point!
128: throw new UnexpectedException(new RuntimeException(
129: "Bug in QuestionCurrLineStartsWithSkipComments"));
130: }
131: }
132: }
|