Adding new code for feature save on unfocus. This is from ticket #542. It also adds...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / actions / AddBlockCommentAction.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.actions;
12
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.ResourceBundle;
16
17 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
18 import net.sourceforge.phpeclipse.phpeditor.php.PHPDocumentPartitioner;
19
20 import org.eclipse.jface.text.Assert;
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.BadPartitioningException;
23 import org.eclipse.jface.text.IDocument;
24 import org.eclipse.jface.text.IDocumentExtension3;
25 import org.eclipse.jface.text.ITextSelection;
26 import org.eclipse.jface.text.ITypedRegion;
27 import org.eclipse.ui.texteditor.ITextEditor;
28
29 /**
30  * Action that encloses the editor's current selection with Java block comment
31  * terminators (<code>&#47;&#42;</code> and <code>&#42;&#47;</code>).
32  * 
33  * @since 3.0
34  */
35 public class AddBlockCommentAction extends BlockCommentAction {
36
37         /**
38          * Creates a new instance.
39          * 
40          * @param bundle
41          *            the resource bundle
42          * @param prefix
43          *            a prefix to be prepended to the various resource keys
44          *            (described in <code>ResourceAction</code> constructor), or
45          *            <code>null</code> if none
46          * @param editor
47          *            the text editor
48          */
49         public AddBlockCommentAction(ResourceBundle bundle, String prefix,
50                         ITextEditor editor) {
51                 super(bundle, prefix, editor);
52         }
53
54         /*
55          * @see net.sourceforge.phpdt.internal.ui.actions.BlockCommentAction#runInternal(org.eclipse.jface.text.ITextSelection,
56          *      org.eclipse.jface.text.IDocumentExtension3,
57          *      net.sourceforge.phpdt.internal.ui.actions.BlockCommentAction.Edit.EditFactory)
58          */
59         protected void runInternal(ITextSelection selection,
60                         IDocumentExtension3 docExtension, Edit.EditFactory factory)
61                         throws BadLocationException, BadPartitioningException {
62                 int selectionOffset = selection.getOffset();
63                 int selectionEndOffset = selectionOffset + selection.getLength();
64                 List edits = new LinkedList();
65                 ITypedRegion partition = docExtension.getPartition(
66                                 IPHPPartitions.PHP_PARTITIONING, selectionOffset, false);
67
68                 handleFirstPartition(partition, edits, factory, selectionOffset);
69
70                 while (partition.getOffset() + partition.getLength() < selectionEndOffset) {
71                         partition = handleInteriorPartition(partition, edits, factory,
72                                         docExtension);
73                 }
74
75                 handleLastPartition(partition, edits, factory, selectionEndOffset);
76
77                 executeEdits(edits);
78         }
79
80         /**
81          * Handle the first partition of the selected text.
82          * 
83          * @param partition
84          * @param edits
85          * @param factory
86          * @param offset
87          */
88         private void handleFirstPartition(ITypedRegion partition, List edits,
89                         Edit.EditFactory factory, int offset) throws BadLocationException {
90
91                 int partOffset = partition.getOffset();
92                 String partType = partition.getType();
93
94                 Assert.isTrue(partOffset <= offset, "illegal partition"); //$NON-NLS-1$
95
96                 // first partition: mark start of comment
97                 if (partType == IDocument.DEFAULT_CONTENT_TYPE
98                                 || partType == PHPDocumentPartitioner.PHP_SCRIPT_CODE) {
99                         // Java code: right where selection starts
100                         edits.add(factory.createEdit(offset, 0, getCommentStart()));
101                 } else if (isSpecialPartition(partType)) {
102                         // special types: include the entire partition
103                         edits.add(factory.createEdit(partOffset, 0, getCommentStart()));
104                 } // javadoc: no mark, will only start after comment
105
106         }
107
108         /**
109          * Handles the end of the given partition and the start of the next
110          * partition, which is returned.
111          * 
112          * @param partition
113          * @param edits
114          * @param factory
115          * @param docExtension
116          * @return
117          * @throws BadLocationException
118          * @throws BadPartitioningException
119          */
120         private ITypedRegion handleInteriorPartition(ITypedRegion partition,
121                         List edits, Edit.EditFactory factory,
122                         IDocumentExtension3 docExtension) throws BadPartitioningException,
123                         BadLocationException {
124
125                 // end of previous partition
126                 String partType = partition.getType();
127                 int partEndOffset = partition.getOffset() + partition.getLength();
128                 int tokenLength = getCommentStart().length();
129
130                 boolean wasJavadoc = false; // true if the previous partition is javadoc
131
132                 if (partType == IPHPPartitions.PHP_PHPDOC_COMMENT) {
133
134                         wasJavadoc = true;
135
136                 } else if (partType == IPHPPartitions.PHP_MULTILINE_COMMENT) {
137
138                         // already in a comment - remove ending mark
139                         edits.add(factory.createEdit(partEndOffset - tokenLength,
140                                         tokenLength, "")); //$NON-NLS-1$
141
142                 }
143
144                 // advance to next partition
145                 partition = docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING,
146                                 partEndOffset, false);
147                 partType = partition.getType();
148
149                 // start of next partition
150                 if (wasJavadoc) {
151
152                         // if previous was javadoc, and the current one is not, then add
153                         // block comment start
154                         if (partType == IDocument.DEFAULT_CONTENT_TYPE
155                                         || partType == PHPDocumentPartitioner.PHP_SCRIPT_CODE
156                                         || isSpecialPartition(partType)) {
157                                 edits.add(factory.createEdit(partition.getOffset(), 0,
158                                                 getCommentStart()));
159                         }
160
161                 } else { // !wasJavadoc
162
163                         if (partType == IPHPPartitions.PHP_PHPDOC_COMMENT) {
164                                 // if next is javadoc, end block comment before
165                                 edits.add(factory.createEdit(partition.getOffset(), 0,
166                                                 getCommentEnd()));
167                         } else if (partType == IPHPPartitions.PHP_MULTILINE_COMMENT) {
168                                 // already in a comment - remove startToken
169                                 edits.add(factory.createEdit(partition.getOffset(),
170                                                 getCommentStart().length(), "")); //$NON-NLS-1$
171                         }
172                 }
173
174                 return partition;
175         }
176
177         /**
178          * Handles the end of the last partition.
179          * 
180          * @param partition
181          * @param edits
182          * @param factory
183          * @param endOffset
184          */
185         private void handleLastPartition(ITypedRegion partition, List edits,
186                         Edit.EditFactory factory, int endOffset)
187                         throws BadLocationException {
188
189                 String partType = partition.getType();
190
191                 if (partType == IDocument.DEFAULT_CONTENT_TYPE
192                                 || partType == PHPDocumentPartitioner.PHP_SCRIPT_CODE) {
193                         // normal java: end comment where selection ends
194                         edits.add(factory.createEdit(endOffset, 0, getCommentEnd()));
195                 } else if (isSpecialPartition(partType)) {
196                         // special types: consume entire partition
197                         edits.add(factory.createEdit(partition.getOffset()
198                                         + partition.getLength(), 0, getCommentEnd()));
199                 }
200
201         }
202
203         /**
204          * Returns whether <code>partType</code> is special, i.e. a Java
205          * <code>String</code>,<code>Character</code>, or
206          * <code>Line End Comment</code> partition.
207          * 
208          * @param partType
209          *            the partition type to check
210          * @return <code>true</code> if <code>partType</code> is special,
211          *         <code>false</code> otherwise
212          */
213         private boolean isSpecialPartition(String partType) {
214                 // return partType == IJavaPartitions.JAVA_CHARACTER
215                 return partType == IPHPPartitions.PHP_STRING_DQ
216                                 || partType == IPHPPartitions.PHP_STRING_SQ
217                                 || partType == IPHPPartitions.PHP_STRING_HEREDOC
218                                 || partType == IPHPPartitions.PHP_SINGLELINE_COMMENT;
219         }
220
221         /*
222          * @see net.sourceforge.phpdt.internal.ui.actions.BlockCommentAction#validSelection(org.eclipse.jface.text.ITextSelection)
223          */
224         protected boolean isValidSelection(ITextSelection selection) {
225                 return selection != null && !selection.isEmpty()
226                                 && selection.getLength() > 0;
227         }
228
229 }