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 edu.rice.cs.drjava.model.AbstractDJDocument;
040: import edu.rice.cs.drjava.DrJava;
041: import edu.rice.cs.drjava.config.OptionConstants;
042:
043: /** Singleton class to construct and use the indentation decision tree.
044: * @version $Id: Indenter.java 4255 2007-08-28 19:17:37Z mgricken $
045: */
046: public class Indenter {
047:
048: public Indenter(int indentLevel) {
049: buildTree(indentLevel);
050: }
051:
052: /**
053: * Enumeration of reasons why indentation may be preformed.
054: * */
055: public enum IndentReason {
056: /** Indicates that an enter key press caused the indentation. This is important for some rules dealing with stars
057: * at the line start in multiline comments
058: */
059: ENTER_KEY_PRESS,
060: /** Indicates that indentation was started for some other reason. This is important for some rules dealing with stars
061: * at the line start in multiline comments
062: */
063: OTHER
064: }
065:
066: /** Root of decision tree. */
067: protected IndentRule _topRule;
068:
069: /** Builds the decision tree for indentation.
070: * For now, this method needs to be called every time the size of one indent level is being changed!
071: */
072: public void buildTree(int indentLevel) {
073: char[] indent = new char[indentLevel];
074: java.util.Arrays.fill(indent, ' ');
075: final String oneLevel = new String(indent);
076:
077: boolean autoCloseComments = DrJava.getConfig().getSetting(
078: OptionConstants.AUTO_CLOSE_COMMENTS).booleanValue();
079:
080: IndentRule
081: // Main tree
082: rule60 = new ActionStartPrevLinePlus(""), rule37 = new ActionStartCurrStmtPlus(
083: oneLevel), rule36 = new ActionStartStmtOfBracePlus(
084: oneLevel), rule35 = rule37, rule34 = new QuestionExistsCharInStmt(
085: '?', ':', rule35, rule36), rule33 = new QuestionLineContains(
086: ':', rule34, rule37), rule32 = new ActionStartCurrStmtPlus(
087: ""), rule31 = new QuestionCurrLineStartsWithSkipComments(
088: "{", rule32, rule33), rule39 = new ActionStartPrevStmtPlus(
089: "", true), rule29 = rule36, rule28 = new ActionStartPrevStmtPlus(
090: "", false), rule40 = rule28, rule30 = new QuestionExistsCharInPrevStmt(
091: '?', rule40, rule39), rule27 = new QuestionExistsCharInStmt(
092: '?', ':', rule28, rule29), rule26 = new QuestionLineContains(
093: ':', rule27, rule30), rule25 = new QuestionStartingNewStmt(
094: rule26, rule31), // no preceding open brace
095: rule24 = new QuestionPrevLineStartsWith("@", rule60, rule25), rule23 = rule36, rule22 = new QuestionHasCharPrecedingOpenBrace(
096: new char[] { '=', ',', '{' }, rule23, rule24), rule21 = rule36, rule20 = new QuestionStartAfterOpenBrace(
097: rule21, rule22), rule19 = new ActionStartStmtOfBracePlus(
098: ""), rule18 = new QuestionCurrLineStartsWithSkipComments(
099: "}", rule19, rule20), // ANONYMOUS inner class formatting breaks here
100: rule17 = new QuestionBraceIsCurly(rule18, rule24), // enclosing block/expr-list opens with '{'?
101: rule16 = new ActionBracePlus(" " + oneLevel), rule15 = new ActionBracePlus(
102: " "), rule38 = new QuestionCurrLineStartsWith(")",
103: rule30, rule15), // does current line start with ')'?
104: rule14 = new QuestionNewParenPhrase(rule38, rule16), // is current line new phrase after open paren?
105: rule13 = new QuestionBraceIsParenOrBracket(rule14, rule17), // enclosing block/expr-list opens with "(" or "["?
106:
107: // Comment tree
108: rule12 = new ActionStartPrevLinePlus(""), rule11 = rule12, rule10 = new ActionStartPrevLinePlus(
109: "* "), rule09 = new QuestionCurrLineEmptyOrEnterPress(
110: rule10, rule11), rule08 = rule12, rule07 = new QuestionCurrLineStartsWith(
111: "*", rule08, rule09), rule06 = new QuestionPrevLineStartsWith(
112: "*", rule07, rule12), rule05 = new ActionStartPrevLinePlus(
113: " "), // padding prefix for interior of ordinary block comment
114: rule04 = new ActionStartPrevLinePlus(" * "), // padding prefix for new line within ordinary block comment
115: rule46 = new ActionStartPrevLinePlus(" * "), // padding prefix for new line within special javadoc block comment
116: rule47 = new ActionStartPrevLinePlus(" "), // padding prefix for interior of special javadoc block comment
117: rule45 = new QuestionPrevLineStartsJavaDocWithText(rule46,
118: rule04), // Prev line begins special javadoc comment?
119: rule48 = new QuestionPrevLineStartsJavaDocWithText(rule47,
120: rule05), // Prev line begins special javadoc comment?
121: rule41 = new ActionStartPrevLinePlusMultilinePreserve(
122: new String[] { " * \n", " */" }, 0, 3, 0, 3), rule49 = new ActionStartPrevLinePlusMultilinePreserve(
123: new String[] { " * \n", " */" }, 0, 4, 0, 4), rule50 = new QuestionPrevLineStartsJavaDocWithText(
124: rule49, rule41),
125:
126: rule03 = new QuestionCurrLineEmptyOrEnterPress(rule45, rule48), rule42 = new QuestionFollowedByStar(
127: rule04, rule41),
128: // rule49 = new ActionStartPrevLinePlusMultilinePreserve(new String[] {" */" }, 0, 4, 0, 4),
129: // rule50 = new QuestionFollowedByStar(rule46, rule49),
130: // rule51 = new QuestionPrevLineStartsJavaDocWithText(rule50, rule42),
131: rule51 = new QuestionCurrLineEmpty(rule50, rule03), // autoClose: rule03 unnecessarily retests CurrentLineEmpty
132: rule02 = new QuestionPrevLineStartsComment(
133: autoCloseComments ? rule51 : rule03, rule06), rule43 = new ActionDoNothing(), rule44 = new QuestionCurrLineIsWingComment(
134: rule43, rule13), rule01 = new QuestionInsideComment(
135: rule02, rule44);
136:
137: _topRule = rule01;
138: }
139:
140: /** Indents the current line based on a decision tree which determines the indent based on context.
141: * @param doc document containing line to be indented
142: * @return true if the condition tested by the top rule holds, false otherwise
143: */
144: public boolean indent(AbstractDJDocument doc,
145: Indenter.IndentReason reason) {
146: // Utilities.showDebug("Indenter.indent called on doc " + doc);
147: return _topRule.indentLine(doc, reason);
148: }
149: }
|