[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [xtext-dev] context dependend formatting
|
Hi,
I agree that it would be valuable for the formatter to have the current
node from the node model available. The current semantic EObject would
also be useful. Please note, that the formatter is not only called by
the DefaultNodeModelFormatter but also by the ParseTreeConstructor. If a
semantic model has been constructed manually or loaded from XMI (i.e. it
has not been created by Xtext's parser), there is no node model at all.
This is the main reason why the current formatter can not rely on the
node model.
You didn't say what your implementation is supposed to do...I can't tell
by the code you've sent since I don't know you grammar. However, the <
/> remind me of XML...
I've spent a lot of work on the formatter during the last two weeks, so
make sure you have a look at Xtext RC1. It will be released today.
Some of the new capabilities are:
- The engine which matches formatting instructions (the thing that is
called by collectLocators(...)) to the grammar elements has gotten much
more powerful. It is now possible to assign formatting instructions to
Groups, Alternatives, UnorderedGroups, ParserRules, DatatypeRules and
TerminalRules. For me this sounds like what you called "context
sensitive formatting". The context is the position within the grammar,
including which parser rules have been entered. In case the formatting
needs more context than give by the grammar (e.g. EAttribute-Values,
EObjects, Lists-sizes from your semantic model) - that's what we call
semantic formatting.
- The formatter can now preserve linebreaks, if needed. See
FormattingConfig.setLinewrap(int minWraps, int defaultWraps, int maxWraps)
- The formatter can now insert arbitrary spaces at defined positions
FormattingConfig.setSpace(String).
cheers,
Moritz
d green wrote:
It would be nice to have the current /AbstractNode/ in method
/FormattingConfigBasedStream::addLineEntry/ available. The
/grammarElement/ and the string /value/ isn't enough for context
sensitiv formatting. The current workaround looks like a function eg
interface in a subclass of /FormattingConfigBasedStream/
protected AbstractNode node = null;
public void setNodeHint(AbstractNode node) {
this.node = node;
}
This is called in a function override in a subclass of
DefaultNodeModelFormatter, eg
@Override
public IFormattedRegion format(CompositeNode root, int offset, int
length) {
List<AbstractNode> nodes = getLeafs(root, offset, offset +
length);
if (nodes.size() == 0)
return null;
String indent = getIndentation(root, offset);
TokenStringBuffer buf = new TokenStringBuffer();
ITokenStream fmt = formatter.createFormatterStream(indent,
buf, false);
// this is xcl
* XclFormattingConfigBasedStream xcl = null;
if ( fmt instanceof XclFormattingConfigBasedStream )
xcl = (XclFormattingConfigBasedStream) fmt;
*
try {
for (AbstractNode n : nodes) {
// this is xcl
* if ( null != xcl)
xcl.setNodeHint(n);
* ...
No you can do context sensitive formatting eg leave the linebreaks out
for an xml-like grammar just for <i>-tags in the subclass of
/FormattingConfigBasedStream/
*protected boolean cleanNext = false;*
@Override
protected void addLineEntry(EObject grammarElement, String value,
boolean isHidden) throws IOException {
Set<ElementLocator> locators = collectLocators(last,
grammarElement);
// System.out.println(loc + " --> " + value.replaceAll("\n",
"\\n"));
* if (cleanNext) {
locators = normalizeLinebreaks(locators);
cleanNext = false;
}
if (value.equals("<") || value.equals("</")) {
// we ar on Start or Stop
if (node.eContainer() instanceof CompositeNode) {
EObject obj = ((CompositeNode)
node.eContainer()).getElement();
if (obj instanceof Start) {
Start start = (Start) obj;
if ("em".equals(start.getStart())) {
locators = normalizeLinebreaks(locators);
}
} else if (obj instanceof Stop) {
Stop stop = (Stop) obj;
if ("em".equals(stop.getStop())) {
locators = normalizeLinebreaks(locators);
}
}
}
} else if (value.equals(">") || value.equals("/>")) {
// we are on the element
if (node.eContainer() instanceof CompositeNode) {
EObject obj = ((CompositeNode)
node.eContainer()).getElement();
if (obj instanceof Start) {
Start start = (Start) obj;
if ("em".equals(start.getStart())) {
cleanNext = true;
}
} else if (obj instanceof Stop) {
Stop elem = ((Stop) obj);
if ("em".equals(elem.getStop())) {
cleanNext = true;
}
}
}
}
*
last = grammarElement;
LineEntry e = new LineEntry(grammarElement, value, true, locators,
preservedWS, indentationLevel);
preservedWS = null;
if (currentLine == null)
currentLine = new Line();
Line newLine = currentLine.add(e);
if (newLine != null)
currentLine = newLine;
}
* protected Set<ElementLocator> normalizeLinebreaks(
Set<ElementLocator> locators) {
Set<ElementLocator> locs = Sets.newHashSet();
for (ElementLocator elm : locators) {
if (!(elm instanceof LinewrapLocator
|| elm instanceof IndentationLocatorStart || elm
instanceof IndentationLocatorEnd))
locs.add(elm);
}
return locs;
}
*
Having /AbstractNode /availiable in /FormattingConfigBasedStream/
would do this in a standard way, at the best in a new overrideable
function like /normalizeCurrent/ with the content of the bold part.
------------------------------------------------------------------------
_______________________________________________
xtext-dev mailing list
xtext-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/xtext-dev
--
Moritz Eysholdt
Software Architect
Telefon: +49 (0) 431 / 5606-335
Mobile: +49 (0) 179 / 6788196
Telefax: +49 (0) 431 / 5606-339
http://www.itemis.de
moritz.eysholdt@xxxxxxxxx
https://www.xing.com/profile/Moritz_Eysholdt
itemis AG
Schauenburgerstraße 116
24118 Kiel
Germany
Rechtlicher Hinweis:
Amtsgericht Dortmund, HRB 20621
Vorstand: Jens Wagener (Vors.), Wolfgang Neuhaus, Dr. Georg Pietrek, Jens Trompeter, Sebastian Neus
Aufsichtsrat: Dr. Burkhard Igel (Vors.), Stephan Grollmann, Michael Neuhaus