package com.aptana.editor.php.internal.ui.editor.formatting; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentCommand; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.source.ISourceViewer; import org2.eclipse.php.internal.core.documentModel.parser.regions.PHPRegionTypes; import com.aptana.core.logging.IdeLog; import com.aptana.editor.php.PHPEditorPlugin; import com.aptana.editor.php.internal.contentAssist.PHPTokenType; import com.aptana.editor.php.internal.ui.editor.PHPSourceViewerConfiguration; import com.aptana.parsing.lexer.Lexeme; /** * PHPDoc indentation strategy * * @author Shalom Gibly <sgibly@aptana.com> */ public class PhpDocAutoIndentStrategy extends AbstractPHPAutoEditStrategy { private static final String PHP_MULTILINE_COMMENT_MID = " * "; //$NON-NLS-1$ private static final String PHP_MULTILINE_COMMENT_END = " */"; //$NON-NLS-1$ /** * PhpDocAutoIndentStrategy * * @param contentType * @param configuration * @param sourceViewer */ public PhpDocAutoIndentStrategy(String contentType, PHPSourceViewerConfiguration configuration, ISourceViewer sourceViewer) { super(contentType, configuration, sourceViewer); } /* * @see IAutoIndentStrategy#customizeDocumentCommand */ public void customizeDocumentCommand(IDocument document, DocumentCommand command) { innerCustomizeDocumentCommand(document, command); this.lexemeProvider = null; } /* * Do the actual customization * @param document * @param command */ private void innerCustomizeDocumentCommand(IDocument document, DocumentCommand command) { if (command.text != null && command.length == 0) { if (TextUtilities.endsWith(document.getLegalLineDelimiters(), command.text) != -1) { int offset = command.offset; try { ITypedRegion region = document.getPartition(offset); if (region != null) { // We only need to ask for the lexemes in the comment and nothing more. getLexemeProvider(document, offset, false); Lexeme<PHPTokenType> lexeme = lexemeProvider.getFloorLexeme(offset); String lexemeType = lexeme.getType().getType(); if (document.getLength() == offset && (lexemeType.equals(PHPRegionTypes.PHPDOC_COMMENT_END) || lexemeType .equals(PHPRegionTypes.PHP_COMMENT_END)) && document.get(offset - 2, 2).equals("*/")) //$NON-NLS-1$ { // get beginning of the multi-line comment or PHPDoc start. // Since we just asked for the lexemes in the offset-region, the lexeme provider holds the // open // lexeme as the first one. Lexeme<PHPTokenType> commentStartLexeme = lexemeProvider.getFirstLexeme(); // Just append the indentation of that line String indent = getIndentationAtOffset(document, commentStartLexeme.getStartingOffset()); // perform the actual work command.shiftsCaret = false; command.caretOffset = command.offset + indent.length(); command.text += indent; return; } } } catch (BadLocationException e) { IdeLog.logError(PHPEditorPlugin.getDefault(), "Error customizing the auto-indent for a PHP documentation block", e); //$NON-NLS-1$ } indentDocAfterNewLine(document, command); } } } /** * Set the indentation from the previous line and adds a space + star. * * @param document * the document to work on * @param command * the command to deal with */ private void indentDocAfterNewLine(IDocument document, DocumentCommand command) { // we need to check if we have a comment end or not. // in case we don't, we add it. Otherwise, we just add a new line with a '*'. Lexeme<PHPTokenType> lastLexeme = this.lexemeProvider.getLastLexeme(); Lexeme<PHPTokenType> firstLexeme = this.lexemeProvider.getFirstLexeme(); String indent = getIndentationAtOffset(document, firstLexeme.getStartingOffset()); String lexemeType = lastLexeme.getType().getType(); StringBuilder builder = new StringBuilder(command.text); builder.append(indent); if (command.offset > firstLexeme.getEndingOffset() && (PHPRegionTypes.PHPDOC_COMMENT_END.equals(lexemeType) || PHPRegionTypes.PHP_COMMENT_END .equals(lexemeType))) { // just add a star with the right indentation builder.append(PHP_MULTILINE_COMMENT_MID); } else { // We also need to add an ending to the comment command.shiftsCaret = false; command.caretOffset = command.offset + command.text.length() + indent.length() + PHP_MULTILINE_COMMENT_MID.length(); builder.append(PHP_MULTILINE_COMMENT_MID); builder.append(command.text); builder.append(indent); builder.append(PHP_MULTILINE_COMMENT_END); } command.text = builder.toString(); // TODO: Shalom - Add the variables, in case we have a constructor, a function or a class method. } }