/*******************************************************************************
* Copyright (c) 2010 Martin Schnabel <mb0@mb0.org>.
* 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 org.axdt.as3.formatting;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.IGrammarAccess;
import org.eclipse.xtext.formatting.IElementMatcherProvider;
import org.eclipse.xtext.formatting.IIndentationInformation;
import org.eclipse.xtext.formatting.IElementMatcherProvider.IElementMatcher;
import org.eclipse.xtext.formatting.impl.BaseFormatter;
import org.eclipse.xtext.formatting.impl.ElementMatcherProvider;
import org.eclipse.xtext.formatting.impl.FormattingConfig;
import org.eclipse.xtext.formatting.impl.MatcherNFAProvider;
import org.eclipse.xtext.formatting.impl.AbstractFormattingConfig.ElementPattern;
import org.eclipse.xtext.formatting.impl.MatcherState;
import org.eclipse.xtext.parsetree.reconstr.IHiddenTokenHelper;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* taken from org.eclipse.xtext.formatting.impl.AbstractDeclarativeFormatter
* @author Moritz Eysholdt - original code
* @author mb0 - changes to make formatter reconfigurable
*/
public abstract class ConfigurableDeclarativeFormatter extends BaseFormatter {
@Singleton
protected static class ConfigStore {
protected FormattingConfig config;
protected IElementMatcherProvider matcherProvider;
}
@Inject
private ConfigStore config;
@Inject
private IGrammarAccess grammarAccess;
@Inject
private IHiddenTokenHelper hiddenTokenHelper;
@Inject(optional = true)
private IIndentationInformation indentInfo = new IIndentationInformation() {
public String getIndentString() {
return "\t";
}
};
protected abstract void configureFormatting(FormattingConfig config);
@SuppressWarnings("deprecation")
protected FormattingConfig createFormattingConfig() {
FormattingConfig cfg = new FormattingConfig(grammarAccess, hiddenTokenHelper, indentInfo);
cfg.setWhitespaceRule(getWSRule());
return cfg;
}
protected IElementMatcher<ElementPattern> createMatcher() {
return getMatcherProvider().createMatcher(getConfig().getLocatorsForSemanticTokens());
}
protected FormattingConfig getConfig() {
synchronized (config) {
if (config.config == null) {
config.config = createFormattingConfig();
config.matcherProvider = new CustomMatcherProvider(grammarAccess);
configureFormatting(config.config);
}
}
return config.config;
}
public void clearConfig() {
synchronized (config) {
config.config = null;
config.matcherProvider = null;
purgeMatcherStateAdapters();
}
}
private void purgeMatcherStateAdapters() {
TreeIterator<EObject> contents = grammarAccess.getGrammar().eAllContents();
List<MatcherState> toRemove = Lists.newArrayList();
while (contents.hasNext()) {
EObject next = contents.next();
if (next instanceof AbstractElement) {
for (Adapter a : next.eAdapters())
if (a instanceof MatcherState)
toRemove.add((MatcherState) a);
}
if (toRemove.isEmpty()) continue;
next.eAdapters().removeAll(toRemove);
toRemove.clear();
}
}
protected IGrammarAccess getGrammarAccess() {
return grammarAccess;
}
protected IHiddenTokenHelper getHiddenTokenHelper() {
return hiddenTokenHelper;
}
protected IIndentationInformation getIndentInfo() {
return indentInfo;
}
protected IElementMatcherProvider getMatcherProvider() {
return config.matcherProvider;
}
protected static class CustomMatcherProvider extends ElementMatcherProvider {
public CustomMatcherProvider(IGrammarAccess grammarAccess) {
grammar = grammarAccess;
nfaProvider = new MatcherNFAProvider();
}
}
}