/*******************************************************************************
* Copyright (c) 2014, 2015 Cisco Systems, Inc. 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
*
*******************************************************************************/
package com.cisco.yangide.editor.editors.text;
import java.util.LinkedList;
import java.util.Map;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.TypedPosition;
import org.eclipse.jface.text.formatter.ContextBasedFormattingStrategy;
import org.eclipse.jface.text.formatter.FormattingContextProperties;
import org.eclipse.jface.text.formatter.IFormattingContext;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import com.cisco.yangide.core.parser.YangFormattingPreferences;
import com.cisco.yangide.editor.YangEditorPlugin;
import com.cisco.yangide.ui.YangUIPlugin;
import com.cisco.yangide.ui.preferences.YangPreferenceConstants;
/**
* @author Konstantin Zaitsev
* @date Jul 21, 2014
*/
public class YangFormattingStrategy extends ContextBasedFormattingStrategy {
/** Documents to be formatted by this strategy */
private final LinkedList<IDocument> documents = new LinkedList<IDocument>();
/** Partitions to be formatted by this strategy */
private final LinkedList<TypedPosition> partitions = new LinkedList<TypedPosition>();
@SuppressWarnings("unchecked")
@Override
public void format() {
super.format();
final IDocument document = documents.removeFirst();
final TypedPosition partition = partitions.removeFirst();
if (document != null && partition != null) {
Map<String, IDocumentPartitioner> partitioners = null;
try {
YangFormattingPreferences pref = new YangFormattingPreferences();
IPreferenceStore store = YangUIPlugin.getDefault().getPreferenceStore();
pref.setSpaceForTabs(store.getBoolean(YangPreferenceConstants.FMT_INDENT_SPACE));
pref.setIndentSize(store.getInt(YangPreferenceConstants.FMT_INDENT_WIDTH));
pref.setCompactImport(store.getBoolean(YangPreferenceConstants.FMT_COMPACT_IMPORT));
pref.setFormatComment(store.getBoolean(YangPreferenceConstants.FMT_COMMENT));
pref.setFormatStrings(store.getBoolean(YangPreferenceConstants.FMT_STRING));
pref.setMaxLineLength(store.getInt(YangPreferenceConstants.FMT_MAX_LINE_LENGTH));
int offset = partition.getOffset();
final TextEdit edit = new YangCodeFormatter(pref).format(document.get(), offset, partition.getLength(),
getIndentationLevel(document, offset), TextUtilities.getDefaultLineDelimiter(document));
if (edit != null) {
if (edit.getChildrenSize() > 20) {
partitioners = TextUtilities.removeDocumentPartitioners(document);
}
edit.apply(document);
}
} catch (MalformedTreeException | BadLocationException e) {
YangEditorPlugin.log(e);
} finally {
if (partitioners != null) {
TextUtilities.addDocumentPartitioners(document, partitioners);
}
}
}
}
@Override
public void formatterStarts(final IFormattingContext context) {
super.formatterStarts(context);
partitions.addLast((TypedPosition) context.getProperty(FormattingContextProperties.CONTEXT_PARTITION));
documents.addLast((IDocument) context.getProperty(FormattingContextProperties.CONTEXT_MEDIUM));
}
@Override
public void formatterStops() {
super.formatterStops();
partitions.clear();
documents.clear();
}
private int getIndentationLevel(IDocument doc, int offset) {
int indentationLevel = 0;
boolean skip = false;
char[] buff = doc.get().toCharArray();
for (int i = 1; i < offset; i++) {
if (buff[i - 1] == '/' && buff[i] == '*') {
skip = true;
}
if (buff[i - 1] == '*' && buff[i] == '/') {
skip = false;
}
if (!skip) {
if (buff[i] == '{') {
indentationLevel++;
}
if (buff[i] == '}') {
indentationLevel--;
}
}
}
return indentationLevel > 0 ? indentationLevel : 0;
}
}