001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * Portions Copyrighted 2007 Sun Microsystems, Inc.
027: */
028: package org.netbeans.modules.ruby.hints;
029:
030: import java.io.IOException;
031: import java.util.Collections;
032: import java.util.List;
033: import java.util.Set;
034: import javax.swing.text.BadLocationException;
035: import org.netbeans.modules.gsf.api.CompilationInfo;
036: import org.netbeans.modules.gsf.api.Error;
037: import org.netbeans.modules.gsf.api.OffsetRange;
038: import org.netbeans.editor.BaseDocument;
039: import org.netbeans.editor.Utilities;
040: import org.netbeans.modules.ruby.hints.spi.Description;
041: import org.netbeans.modules.ruby.hints.spi.EditList;
042: import org.netbeans.modules.ruby.hints.spi.ErrorRule;
043: import org.netbeans.modules.ruby.hints.spi.Fix;
044: import org.netbeans.modules.ruby.hints.spi.HintSeverity;
045: import org.netbeans.modules.ruby.hints.spi.PreviewableFix;
046: import org.netbeans.modules.ruby.hints.spi.RuleContext;
047: import org.netbeans.modules.ruby.lexer.LexUtilities;
048: import org.openide.util.Exceptions;
049: import org.openide.util.NbBundle;
050:
051: /**
052: * Rule which identifies common syntax errors and offers to help
053: *
054: * @author Tor Norbye
055: */
056: public class CommonSyntaxErrors implements ErrorRule {
057:
058: public Set<String> getCodes() {
059: // Add more as necessary
060: return Collections.singleton("Syntax error, unexpected '=' "); // NOI18N
061: }
062:
063: public void run(RuleContext context, Error error,
064: List<Description> result) {
065: CompilationInfo info = context.compilationInfo;
066:
067: // See if it's a "begin"
068: try {
069: // TODO - if we get many codes, switch on these here!
070: BaseDocument doc = context.doc;
071: int astOffset = error.getStartPosition();
072: int lexOffset = LexUtilities
073: .getLexerOffset(info, astOffset);
074: if (lexOffset == -1) {
075: return;
076: }
077: if ((lexOffset < doc.getLength() - "begin".length()) && // NOI18N
078: "begin".equals(doc.getText(lexOffset, "begin"
079: .length()))) { // NOI18N
080: OffsetRange range = new OffsetRange(lexOffset - 1,
081: lexOffset + "=begin".length());
082: Fix fix = new FixDocIndent(info, lexOffset - 1);
083: List<Fix> fixList = Collections.singletonList(fix);
084: String displayName = NbBundle.getMessage(
085: CommonSyntaxErrors.class, "DontIndentDocs");
086: Description desc = new Description(this , displayName,
087: info.getFileObject(), range, fixList, 500);
088: result.add(desc);
089: }
090: } catch (BadLocationException ex) {
091: Exceptions.printStackTrace(ex);
092: }
093: }
094:
095: public boolean appliesTo(CompilationInfo compilationInfo) {
096: return true;
097: }
098:
099: public String getDisplayName() {
100: return "X";
101: }
102:
103: private class FixDocIndent implements PreviewableFix {
104: private CompilationInfo info;
105: private int equalOffset;
106:
107: private FixDocIndent(CompilationInfo info, int equalOffset) {
108: this .info = info;
109: this .equalOffset = equalOffset;
110: }
111:
112: public String getDescription() {
113: return NbBundle.getMessage(CommonSyntaxErrors.class,
114: "ReindentBegin");
115: }
116:
117: public void implement() throws Exception {
118: getEditList().apply();
119: }
120:
121: public EditList getEditList() throws Exception {
122: // Move code - but I've gotta make sure I create a new line if necessary
123: BaseDocument doc = (BaseDocument) info.getDocument();
124:
125: if (equalOffset > doc.getLength()) {
126: return null; // recent edits
127: }
128:
129: EditList edits = new EditList(doc);
130:
131: int rowStart = Utilities.getRowStart(doc, equalOffset);
132: if (Utilities.getRowFirstNonWhite(doc, equalOffset) < equalOffset) {
133: // There's something else on this line! Create a newline instead!
134: edits.replace(equalOffset, 0, "\n", false, 0);
135: } else {
136: edits.replace(rowStart, equalOffset - rowStart, null,
137: false, 0);
138: }
139: int nextRow = Utilities.getRowEnd(doc, rowStart) + 1;
140: if (nextRow < doc.getLength()) {
141: String text = doc.getText(nextRow, doc.getLength()
142: - nextRow);
143: int index = text.indexOf("=end");
144: if (index != -1) {
145: int beginIndex = text.indexOf("=begin");
146: if (index < beginIndex || beginIndex == -1) {
147: int offset = nextRow + index;
148: rowStart = Utilities.getRowStart(doc, offset);
149: if (Utilities.getRowFirstNonWhite(doc, offset) < offset) {
150: // There's something else on this line! Create a newline instead!
151: edits.replace(offset, 0, "\n", false, 1);
152: } else {
153: edits.replace(rowStart, offset - rowStart,
154: null, false, 1);
155: }
156: }
157: }
158: }
159:
160: return edits;
161: }
162:
163: public boolean isSafe() {
164: return true;
165: }
166:
167: public boolean isInteractive() {
168: return false;
169: }
170:
171: public boolean canPreview() {
172: return true;
173: }
174: }
175:
176: public boolean showInTasklist() {
177: return true;
178: }
179:
180: public HintSeverity getDefaultSeverity() {
181: return HintSeverity.ERROR;
182: }
183:
184: }
|