| /******************************************************************************* |
| * Copyright (c) 2011, 2014 Sierra Wireless and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Sierra Wireless - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ldt.ui.internal.editor.formatter; |
| |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.dltk.formatter.AbstractScriptFormatter; |
| import org.eclipse.dltk.ui.formatter.FormatterException; |
| import org.eclipse.dltk.ui.formatter.IScriptFormatterExtension; |
| import org.eclipse.dltk.ui.text.util.TabStyle; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.ldt.core.grammar.IGrammar; |
| import org.eclipse.ldt.core.grammar.ILuaSourceValidator; |
| import org.eclipse.ldt.core.internal.formatter.LuaFormatterException; |
| import org.eclipse.ldt.core.internal.formatter.LuaFormatterModule; |
| import org.eclipse.ldt.core.internal.grammar.LuaGrammarManager; |
| import org.eclipse.ldt.ui.internal.Activator; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.text.edits.ReplaceEdit; |
| import org.eclipse.text.edits.TextEdit; |
| |
| public class LuaFormatter extends AbstractScriptFormatter implements IScriptFormatterExtension { |
| static final String ID = "org.eclipse.ldt.formatter"; //$NON-NLS-1$ |
| private final TabStyle tabPolicy; |
| private final int tabSize; |
| private final int indentationSize; |
| private final String delimiter; |
| private final String tabulation; |
| private final boolean formatTableValues; |
| private IProject project; |
| |
| private static final LuaFormatterModule LUA_FORMAT_MODULE = new LuaFormatterModule(); |
| |
| protected LuaFormatter(final String lineDelimiter, final Map<String, String> preferences) { |
| super(preferences); |
| delimiter = lineDelimiter; |
| /* |
| * Get formatting constants from preferences |
| */ |
| tabPolicy = TabStyle.forName(preferences.get(LuaFormatterPreferenceConstants.FORMATTER_TAB_CHAR)); |
| String string = preferences.get(LuaFormatterPreferenceConstants.FORMATTER_TAB_SIZE); |
| tabSize = (string == null || string.isEmpty()) ? 0 : Integer.parseInt(string); |
| string = preferences.get(LuaFormatterPreferenceConstants.FORMATTER_INDENTATION_SIZE); |
| indentationSize = (string == null || string.isEmpty()) ? 0 : Integer.parseInt(string); |
| string = preferences.get(LuaFormatterPreferenceConstants.FORMATTER_INDENT_TABLE_VALUES); |
| formatTableValues = (string == null || string.isEmpty()) ? false : Boolean.parseBoolean(string); |
| |
| /* |
| * Build separator character |
| */ |
| // Concatenate spaces |
| if (tabPolicy == TabStyle.SPACES) { |
| final char space = ' '; |
| // Create tabulation |
| final StringBuilder sb = new StringBuilder(tabSize); |
| for (int k = 0; k < tabSize; k++) { |
| sb.append(space); |
| } |
| tabulation = sb.toString(); |
| } else { |
| // Use single tabulation |
| tabulation = "\t"; //$NON-NLS-1$ |
| } |
| } |
| |
| private ILuaSourceValidator getValidator() { |
| // Get grammar |
| IGrammar grammar = LuaGrammarManager.getDefaultGrammarFor(project); |
| if (grammar != null) |
| return grammar.getValidator(); |
| return null; |
| } |
| |
| /** |
| * @see org.eclipse.dltk.ui.formatter.IScriptFormatter#format(String, int, int, int) |
| */ |
| @Override |
| public TextEdit format(final String source, final int offset, final int length, final int indentationLevel) throws FormatterException { |
| |
| // valid lua code |
| ILuaSourceValidator validator = getValidator(); |
| if (validator != null) { |
| boolean valid = validator.valid(source); |
| if (!valid) { |
| throw new FormatterException("can not format file with error :" + validator.getErrorMessage()); //$NON-NLS-1$ |
| } |
| } |
| |
| /* |
| * Format given source code |
| */ |
| final String formatted; |
| try { |
| // With mixed white spaces |
| if (tabPolicy == TabStyle.MIXED) { |
| formatted = LUA_FORMAT_MODULE.indent(source, delimiter, formatTableValues, tabSize, indentationSize); |
| } else { |
| // With one type of tabulation |
| formatted = LUA_FORMAT_MODULE.indent(source, delimiter, formatTableValues, tabulation); |
| } |
| } catch (final LuaFormatterException e) { |
| // TODO Show this to user |
| throw new FormatterException(e); |
| |
| } |
| |
| if (length < source.length()) { |
| final Document doc = new Document(source); |
| try { |
| // Get line change range form original source |
| final int startLine = doc.getLineOfOffset(offset); |
| final int endLine = doc.getLineOfOffset(offset + length); |
| |
| /* |
| * Get source code from those lines in formatted code |
| */ |
| final StringBuffer code = new StringBuffer(); |
| final Document formattedDoc = new Document(formatted); |
| int lengthToReplace = 0; |
| for (int line = startLine; line <= endLine; line++) { |
| // Sum selected text length |
| lengthToReplace += doc.getLineLength(line); |
| |
| // Retrieve formatted code |
| final IRegion lineDescription = formattedDoc.getLineInformation(line); |
| final String codeOnTheLine = formattedDoc.get(lineDescription.getOffset(), lineDescription.getLength()); |
| code.append(codeOnTheLine); |
| |
| // Append new line when needed |
| final String lineEnd = formattedDoc.getLineDelimiter(line); |
| if (lineEnd != null) { |
| code.append(lineEnd); |
| } |
| } |
| final int selectionStartOffset = doc.getLineOffset(startLine); |
| return new ReplaceEdit(selectionStartOffset, lengthToReplace, code.toString()); |
| } catch (final BadLocationException e) { |
| MessageDialog.openError(Display.getDefault().getActiveShell(), Messages.LuaFormatterErrorWhileFormattingTitle, |
| Messages.LuaFormatterUnableToFormatSelection); |
| Activator.logError(Messages.LuaFormatterUnableToFormatSelection, e); |
| } |
| } else if (source.equals(formatted)) { |
| // If no modification have be done on the source code when formatting, |
| // avoid the editor to be dirty/stale mode by returning null |
| return null; |
| } |
| // Construct text edition |
| return new ReplaceEdit(offset, length, formatted); |
| } |
| |
| @Override |
| public int detectIndentationLevel(final IDocument document, final int offset) { |
| return 0; |
| } |
| |
| /** |
| * @see org.eclipse.dltk.ui.formatter.IScriptFormatterExtension#initialize(org.eclipse.core.resources.IProject) |
| */ |
| @Override |
| public void initialize(IProject p) { |
| project = p; |
| } |
| } |