Package com.puppetlabs.geppetto.pp.dsl.formatting

Source Code of com.puppetlabs.geppetto.pp.dsl.formatting.PPStylesheetProvider

/**
* Copyright (c) 2013 Puppet Labs, Inc. and other contributors, as listed below.
* 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:
*   Puppet Labs
*/
package com.puppetlabs.geppetto.pp.dsl.formatting;

import com.puppetlabs.geppetto.pp.dsl.formatting.PPSemanticLayout.ResourceStyle;
import com.puppetlabs.geppetto.pp.dsl.formatting.PPSemanticLayout.StatementStyle;
import com.puppetlabs.geppetto.pp.dsl.services.PPGrammarAccess;
import com.puppetlabs.geppetto.pp.dsl.services.PPGrammarAccess.ResourceExpressionElements;
import com.puppetlabs.xtext.dommodel.IDomNode.NodeType;
import com.puppetlabs.xtext.dommodel.formatter.css.DefaultStylesheetProvider;
import com.puppetlabs.xtext.dommodel.formatter.css.DomCSS;
import com.puppetlabs.xtext.dommodel.formatter.css.IFunctionFactory;
import com.puppetlabs.xtext.dommodel.formatter.css.IStyleFactory;
import com.puppetlabs.xtext.dommodel.formatter.css.Select;
import com.puppetlabs.xtext.dommodel.formatter.css.Select.Selector;
import com.puppetlabs.xtext.dommodel.formatter.css.StyleSet;

import com.google.common.collect.Iterables;
import com.google.inject.Inject;

/**
* Provides the style sheet for PP.
*
*/
public class PPStylesheetProvider extends DefaultStylesheetProvider {

  @Inject
  private IStyleFactory styles;

  @Inject
  private IFunctionFactory functions;

  @Inject
  PPGrammarAccess grammarAccess;

  @Override
  public DomCSS get() {

    // look up grammar elements and create reusable selectors to make the style sheet more readable
    //
    final Selector attributeOperationsComma = Select.grammar(grammarAccess.getAttributeOperationsAccess().getCommaKeyword_1_0_0());

    final Selector resourceBodyTitleColon = Select.grammar(grammarAccess.getResourceBodyAccess().getColonKeyword_0_1());

    final Selector resourceSingleBodyTitle = Select.node(ResourceStyle.SINGLEBODY_TITLE);
    final Selector resourceSingleBodyNoTitle = Select.node(ResourceStyle.SINGLEBODY_NO_TITLE);
    final Selector resourceCompactable = Select.node(ResourceStyle.COMPACTABLE);
    final Selector inline = Select.node(StatementStyle.INLINE);
    final Selector notInline = Select.not(Select.node(StatementStyle.INLINE));

    final Selector lambdaLeftBrace = Select.grammar(
      grammarAccess.getJava8LambdaAccess().getLeftCurlyBracketKeyword_5(),
      grammarAccess.getRubyLambdaAccess().getLAMBDATerminalRuleCall_0());

    final Selector lambdaRightBrace = Select.grammar(
      grammarAccess.getJava8LambdaAccess().getRightCurlyBracketKeyword_7(),
      grammarAccess.getRubyLambdaAccess().getRightCurlyBracketKeyword_6());

    final Selector inCompactableResource = Select.containment(resourceCompactable);
    final Selector inASingleBodiesResourceWithTitle = Select.containment(resourceSingleBodyTitle);
    final Selector inASingleBodiesResourceWithoutTitle = Select.containment(resourceSingleBodyNoTitle);

    final ResourceExpressionElements resourceExpressionAccess = grammarAccess.getResourceExpressionAccess();
    final Selector resourceLeftCurlyBracket = Select.grammar(resourceExpressionAccess.findKeywords("{"));
    final Selector resourceRightCurlyBracket = Select.grammar(resourceExpressionAccess.findKeywords("}"));
    final Selector resourceBodySemicolon = Select.grammar(resourceExpressionAccess.findKeywords(";"));
    final Selector optionalResourceEndBodySemicolon = Select.grammar(
      resourceExpressionAccess.getSemicolonKeyword_0_1_2_2(), //
      resourceExpressionAccess.getSemicolonKeyword_1_3_2());

    final Selector elseAndElsifKeywords = Select.grammar(Iterables.concat(
      grammarAccess.getIfExpressionAccess().findKeywords("else", "elsif"), //
      grammarAccess.getElseIfExpressionAccess().findKeywords("else", "elsif")));

    final Selector relationshipEdgeOperator = Select.grammar(grammarAccess.getRelationshipExpressionAccess().getOpNameEdgeOperatorParserRuleCall_1_1_0());
    final Selector atExpressionLeftBracket = Select.grammar(grammarAccess.getAtExpressionAccess().getLeftSquareBracketKeyword_1_1());

    // interpolation
    final Selector interpolationStart = Select.grammar(
      grammarAccess.getTextExpressionAccess().getDollarSignLeftCurlyBracketKeyword_1_1(), //
      grammarAccess.getUnquotedStringAccess().getDollarSignLeftCurlyBracketKeyword_1());
    final Selector interpolationEnd = Select.grammar(
      grammarAccess.getTextExpressionAccess().getRightCurlyBracketKeyword_1_3(), //
      grammarAccess.getUnquotedStringAccess().getRightCurlyBracketKeyword_3());

    final StyleSet resourceRightCurlyStyleNoDedent = StyleSet.withImmutableStyles(//
      styles.oneLineBreak(), //
      styles.noSpaceUnlessWrapped(), //
      styles.dedent(0));

    final StyleSet noSpaceUnlessWrappedNoLine = StyleSet.withImmutableStyles(
      styles.noSpaceUnlessWrapped(), styles.noLineBreak());
    // final StyleSet noSpaceNoLine = StyleSet.withImmutableStyles(styles.noSpace(), styles.noLineBreak());
    final StyleSet noSpaceOneLine = StyleSet.withImmutableStyles(
      styles.noSpaceUnlessWrapped(), styles.oneLineBreak());
    final StyleSet noSpaceOneLineOptionallyTwo = StyleSet.withImmutableStyles(
      styles.noSpaceUnlessWrapped(), styles.lineBreaks(1, 1, 2));
    final StyleSet noSpaceTwoLines = StyleSet.withImmutableStyles(
      styles.noSpaceUnlessWrapped(), styles.lineBreaks(2, 2, 2));
    final StyleSet oneSpaceNoLine = StyleSet.withImmutableStyles(styles.oneSpace(), styles.noLineBreak());
    final StyleSet oneOptionalSpaceNoLine = StyleSet.withImmutableStyles(//
      styles.oneSpace(), styles.noLineBreak());
    final StyleSet oneSpaceOneOptionalLine = StyleSet.withImmutableStyles(//
      styles.oneSpace(), styles.lineBreaks(0, 0, 1, true, true));

    DomCSS css = super.get();

    css.addRules(
      // RESOURCE
      // Resource expression with single titled body, should allow body to have title on same line
      // so, no line break, but one space here
      Select.and(inASingleBodiesResourceWithTitle, Select.whitespaceAfter(resourceLeftCurlyBracket)) //
      .withStyles( //
        styles.noLineBreak(), //
        styles.oneSpace(), //
        styles.indent(0))//
      .withRuleName("WsAfterLeftCurlyBracket.InASingleBodiedResourceWithTitle"),

      // Resource expression with single body without title, should not indent, as the body is
      // indented
      Select.and(inASingleBodiesResourceWithoutTitle, Select.whitespaceAfter(resourceLeftCurlyBracket)) //
      .withStyles( //
        styles.oneLineBreak(), //
        styles.indent(0)) //
      .withRuleName("WsAfterLeftCurlyBracket.InASingleBodiedResourceWithoutTitle"),

      Select.and(Select.important(inCompactableResource), Select.whitespaceBefore(resourceRightCurlyBracket)) //
      .withStyles(styles.noLineBreak(), styles.oneSpace()) //
      .withRuleName("WsBeforeRightCurlyBracket-Compactable"), //

      Select.and(inASingleBodiesResourceWithTitle, Select.whitespaceBefore(resourceRightCurlyBracket)) //
      .withStyle(resourceRightCurlyStyleNoDedent)//
      .withRuleName("WsBeforeRightCurlyBracket.InASingleBodiesResourceWithTitle."),

      Select.and(inASingleBodiesResourceWithoutTitle, Select.whitespaceBefore(resourceRightCurlyBracket)) //
      .withStyle(resourceRightCurlyStyleNoDedent)//
      .withRuleName("WsBeforeRightCurlyBracket.InASingleBodiesResourceWithoutTitle."),

      // break bodies apart on body semicolon
      Select.whitespaceAfter(resourceBodySemicolon).withStyles(//
        styles.lineBreaks(2, 2, 2)).withRuleName("WsAfterResourceBodySemicolon"),
      Select.whitespaceBefore(resourceBodySemicolon).withStyles(//
        styles.noSpaceUnlessWrapped(), //
        styles.noLineBreak())//
      .withRuleName("WsBeforeResourceBodySemicolon"),

      // only one line break after the end semicolon
      Select.whitespaceAfter(Select.important(optionalResourceEndBodySemicolon))//
      .withStyles(//
        styles.noSpaceUnlessWrapped(), //
        styles.oneLineBreak())//
      .withRuleName("WsAfterImportantResourceEndBodySemicolon"),

      // Note: Closing Resource "}" has DEDENT BREAK "}" BREAK by default

      // RESOURCE BODY
      // No space before the resource body title colon
      Select.whitespaceBefore(resourceBodyTitleColon)//
      .withStyles(styles.noSpaceUnlessWrapped())//
      .withRuleName("WsBeforeResourceBodyTitleColon"),

      // A resource body has its attribute operations indented after the title ':'
      // If compact, stay on the same line
      Select.and(inCompactableResource, Select.whitespaceAfter(resourceBodyTitleColon)) //
      .withStyle(oneSpaceNoLine) //
      .withRuleName("WsAfterResourceBodyTitleColon-Compactable"), //

      Select.whitespaceAfter(resourceBodyTitleColon)//
      .withStyles( //
        styles.oneLineBreak())//
      .withRuleName("WsAfterResourceBodyTitleColon"), //

      // ATTRIBUTE OPERATIONS have each operation on a separate line
      // a => b, c => d
      // -------^
      // If compact, stay on the same line
      Select.and(inCompactableResource, Select.whitespaceAfter(attributeOperationsComma)) //
      .withStyle(oneSpaceNoLine) //
      .withRuleName("WsAfterAttributeOperationsComma-Compactable"), //

      Select.whitespaceAfter(attributeOperationsComma)//
      .withStyles(styles.oneLineBreak())//
      .withRuleName("WsAfterAttributeOperationsComma"),

      // xxx []
      // ---^
      Select.whitespaceBefore(atExpressionLeftBracket)//
      .withStyles(styles.noSpaceUnlessWrapped(), //
        styles.noLineBreak())//
      .withRuleName("WsbeforeAtExpressionLeftBracket"),

      // @ name
      // -^
      // @@ name
      // --^
      Select.whitespaceAfter(Select.keyword("@"))//
      .withStyle(noSpaceUnlessWrappedNoLine)//
      .withRuleName("WsAfterKeyword@"),
      Select.whitespaceAfter(
        Select.grammar(grammarAccess.getVirtualNameOrReferenceAccess().getExportedATBooleanParserRuleCall_1_0()))//
      .withStyle(noSpaceUnlessWrappedNoLine)//
      .withRuleName("WsAfterExportedMarker@"),

      Select.whitespaceBefore(elseAndElsifKeywords)//
      .withStyle(oneSpaceNoLine)//
      .withRuleName("WsBeforeKeywordsElseAndElseif"), //

      Select.whitespaceAfter(
        Select.grammar(grammarAccess.getUnaryMinusExpressionAccess().getHyphenMinusKeyword_0()))//
      .withStyle(noSpaceUnlessWrappedNoLine)//
      .withRuleName("WsAfterUnaryMinus"), //

      Select.whitespaceAfter(Select.grammar(grammarAccess.getNotExpressionAccess().getExclamationMarkKeyword_0()))//
      .withStyle(noSpaceUnlessWrappedNoLine)//
      .withRuleName("WsAfterUnaryNotEclamationMark"), //

      // Relationships are typically resource {} -> resource {}
      Select.whitespaceBefore(relationshipEdgeOperator)//
      .withStyle(oneSpaceNoLine)//
      .withRuleName("WsBeforeRelationshipEdgeOperator"), //

      Select.whitespaceAfter(relationshipEdgeOperator)//
      .withStyle(oneSpaceOneOptionalLine)//
      .withRuleName("WsAfterRelationshipEdgeOperator"), //

      // --Selector Expression
      Select.whitespaceBefore(
        Select.grammar(grammarAccess.getSelectorExpressionAccess().getCommaKeyword_1_2_0_3()))//
      .withStyle(noSpaceUnlessWrappedNoLine)//
      .withRuleName("WsBeforeSelectorExpressionEndComma"), //

      Select.whitespaceAfter(
        Select.grammar(grammarAccess.getSelectorExpressionAccess().getCommaKeyword_1_2_0_2_0_0()))//
      .withStyle(noSpaceOneLine)//
      .withRuleName("WsAfterSelectorExpressionComma"), //

      Select.whitespaceAfter(//
        Select.grammar(grammarAccess.getSelectorExpressionAccess().getRightCurlyBracketKeyword_1_2_0_4())) //
      .withStyle(oneOptionalSpaceNoLine) //
      .withRuleName("WsAfterSelectorRightBrace"), //

      // --Interpolation
      interpolationStart.withStyle(styles.indent())//
      .withRuleName("InterpolationStart"), //

      Select.whitespaceAfter(interpolationStart)//
      .withStyles(//
        styles.noSpace(), // non wrappable
        styles.noLineBreak()) // may contain a complex expression
      .withRuleName("WsAfterInterpolationStart"), //

      Select.whitespaceBefore(interpolationEnd)//
      .withStyles(//
        styles.noSpace(), // non wrappable
        styles.noLineBreak(), //
        styles.dedent()) // may contain a complex expression
      .withRuleName("WsBeforeInterpolationEnd"), //

      Select.whitespaceAfter(interpolationEnd) //
      .withStyles(//
        styles.noLineBreak()) //
      .withRuleName("WsAfterInterpolationEnd"), //

      // --Statements
      // ws before subsequent statements in a block
      // non inline
      Select.whitespaceBefore(Select.and(//
        Select.not(Select.node(StatementStyle.INLINE)), //
        Select.node(StatementStyle.STATEMENT), //
        Select.node(StatementStyle.BLOCK), //
        Select.not(Select.node(StatementStyle.FIRST))))//
      .withStyle(noSpaceTwoLines)//
      .withRuleName("WsBeforeNonFirstBlockStatement"),

      Select.whitespaceBefore(Select.and(//
        Select.not(Select.node(StatementStyle.INLINE)), //
        Select.node(StatementStyle.STATEMENT), //
        Select.not(Select.node(StatementStyle.FIRST))))//
      .withStyle(noSpaceOneLineOptionallyTwo)//
      .withRuleName("WsBeforeNonFirstStatement"), //

      // inline
      // Although inlined, gets same treatment since it is a block
      Select.whitespaceBefore(Select.and(//
        Select.node(StatementStyle.INLINE), //
        Select.node(StatementStyle.STATEMENT), //
        Select.node(StatementStyle.BLOCK), //
        Select.not(Select.node(StatementStyle.FIRST))))//
      .withStyle(noSpaceTwoLines)//
      .withRuleName("WsBeforeNonFirstBlockStatement"),

      Select.whitespaceBefore(Select.and(//
        Select.node(StatementStyle.INLINE), Select.node(StatementStyle.STATEMENT), //
        Select.not(Select.node(StatementStyle.FIRST))))//
      .withStyles(styles.oneSpace(), styles.noLineBreak())//
      .withRuleName("WsBeforeNonFirstStatement"), //

      // styles.noSpace(), styles.lineBreaks(functions.oneLineBreakUnlessPredecessorIsLinebreakingComment())),

      // No space between function name and ()
      Select.whitespaceBefore(
        Select.grammar(grammarAccess.getFunctionCallAccess().getLeftParenthesisKeyword_1_0_0_1()))//
      // Select.grammar(grammarAccess.getFunctionCallAccess().getLeftParenthesisKeyword_1_1()))//
      .withStyle(noSpaceUnlessWrappedNoLine) //
      .withRuleName("WsBeforeFunctionCallLeftParenthesis"),

      // PP parser includes trailing WS in ML comment, and SL comment always ends with line break
      // These two rules allows the WS before a comment to have a break (even if in an expression)
      // and one space after (unless the predecessor is whitespace terminated).
      Select.whitespaceBefore(Select.node(NodeType.COMMENT))//
      .withStyles(//
        styles.oneSpace(),//
        styles.lineBreaks(0, 0, 2, false, false))//
      .withRuleName("WsBeforeComment"),

      Select.whitespaceAfter(Select.node(NodeType.COMMENT))//
      .withStyles(//
        styles.spacing(functions.oneSpaceUnlessPredecessorIsWhitespaceTerminated()),//
        styles.lineBreaks(0, 0, 2, false, false))//
      .withRuleName("WsAfterComment"),

      // Method Call
      Select.whitespaceBefore(Select.grammar(grammarAccess.getMethodCallAccess().getFullStopKeyword_1_1())) //
      .withStyles(styles.noSpace(), styles.noLineBreak()).withRuleName("WsBeforeDot"),
      Select.whitespaceAfter(Select.grammar(grammarAccess.getMethodCallAccess().getFullStopKeyword_1_1())) //
      .withStyles(styles.noSpace(), styles.noLineBreak()).withRuleName("WsAfterDot"),

      // The x.y() should not have whitespace before and after the opening '(' - the parenthesis are
      // optional (the ')' is handled like all parentheses, but the opening is special
      Select.whitespaceBefore(
        Select.grammar(grammarAccess.getMethodCallAccess().getParenthesizedLPARBooleanParserRuleCall_1_2_1_0_0()))//
      .withStyles(styles.noSpace(), styles.noLineBreak()) //
      .withRuleName("WsBeforeMethodCall_LPAR"),

      // No space after '('
      Select.whitespaceAfter(
        Select.grammar(grammarAccess.getMethodCallAccess().getParenthesizedLPARBooleanParserRuleCall_1_2_1_0_0()))//
      .withStyles(styles.noSpaceUnlessWrapped())//
      .withRuleName("NoSpaceAfterMethodCallLeftParenthesis"), //

      // Lambdas
      Select.whitespaceAfter(Select.grammar(grammarAccess.getJava8LambdaAccess().getVerticalLineKeyword_0())) //
      .withStyle(styles.noSpace()).withRuleName("WsAfterLeftJ8Pipe"),
      Select.whitespaceBefore(Select.grammar(grammarAccess.getJava8LambdaAccess().getVerticalLineKeyword_3())) //
      .withStyle(styles.noSpace()).withRuleName("WsBeforeRightJ8Pipe"),
      Select.whitespaceBefore(Select.grammar(grammarAccess.getRubyLambdaAccess().getVerticalLineKeyword_1())) //
      .withStyle(styles.noSpace()).withRuleName("WsBeforeLeftRPipe"),
      Select.whitespaceAfter(Select.grammar(grammarAccess.getRubyLambdaAccess().getVerticalLineKeyword_1())) //
      .withStyle(styles.noSpace()).withRuleName("WsAfterLeftRPipe"),
      Select.whitespaceBefore(Select.grammar(grammarAccess.getRubyLambdaAccess().getVerticalLineKeyword_4())) //
      .withStyle(styles.noSpace()).withRuleName("WsBeforeRightRPipe"),

      Select.whitespaceAfter(
        Select.grammar(grammarAccess.getRubyLambdaAccess().getVerticalLineKeyword_4()).and(inline)) //
      .withStyles(styles.oneSpace(), styles.indent(0), styles.noLineBreak()).withRuleName(
        "WsAfterInlineRightRPipe"),
      Select.whitespaceAfter(Select.grammar(grammarAccess.getRubyLambdaAccess().getVerticalLineKeyword_4())) //
      .withStyles(styles.indent(), styles.oneLineBreak()).withRuleName("WsAfterRightRPipe"),

      // Start indent on lambda '{' that is inline (in case there is a break)
      Select.whitespaceAfter(lambdaLeftBrace.and(inline)).//
      withStyles( //
        styles.indent(), //
        styles.oneSpace(), //
        styles.noLineBreak())//
      .withRuleName("WsAfterInlineLambdaLeftBrace"), //

      // Stop indent on '}' and emit one space before
      Select.whitespaceBefore(lambdaRightBrace.and(inline))//
      .withStyles( //
        styles.oneSpace(), //
        styles.dedent(), //
        styles.noLineBreak()) //
      .withRuleName("WsAfterInlineLambdaRightBrace"), //

      // No space and optinal one linebreak after a lambda '}' if inline
      Select.whitespaceAfter(lambdaRightBrace.and(inline))//
      .withStyles( //
        styles.noSpaceUnlessWrapped(), //
        styles.lineBreaks(0, 1, 2)) //
      .withRuleName("DefaultCSS.BreakLineAfterRightCurlyBrace"),

      // Separator
      Select.whitespaceBefore(
        Select.grammar(grammarAccess.getSeparatorExpressionAccess().getSemicolonKeyword_1())) //
      .withStyles(styles.noSpace(), styles.noLineBreak()).withRuleName("WsBeforeSeparator"),

      // optional linebreak if non inline
      Select.whitespaceAfter( //
        Select.and(
          notInline, Select.grammar(grammarAccess.getSeparatorExpressionAccess().getSemicolonKeyword_1()))) //
      .withStyles(styles.oneSpace(), styles.lineBreaks(0, 1, 1, true, true)) //
      .withRuleName("WsAfterSeparator"),

      // no linebreak if inlining
      Select.whitespaceAfter(Select.and( //
        Select.grammar(grammarAccess.getSeparatorExpressionAccess().getSemicolonKeyword_1()), //
        inline))//
      .withStyles(styles.oneSpace(), styles.noLineBreak()) //
      .withRuleName("WsAfterSeparator")

    // ,

    // Select.whitespaceBefore(Select.grammar(grammarAccess.getLiteralListAccess().getEndCommaParserRuleCall_3())).withStyle(//
    // noSpaceNoLine)

    );
    return css;
  }
}
TOP

Related Classes of com.puppetlabs.geppetto.pp.dsl.formatting.PPStylesheetProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.