private static Block generateGoFileBlock(ASTNode node, CommonCodeStyleSettings settings) {
   return new GoFileBlock(
       node,
       Alignment.createAlignment(),
       Indent.getAbsoluteNoneIndent(),
       Wrap.createWrap(WrapType.NONE, false),
       settings);
 }
  public static Block generateBlock(
      ASTNode node, Indent indent, Alignment alignment, CommonCodeStyleSettings styleSettings) {
    PsiElement psi = node.getPsi();
    if (psi instanceof GoBlockStatement)
      return new GoBlockStatementBlock(node, indent, styleSettings);

    if (psi instanceof GoFile) return generateGoFileBlock(node, styleSettings);

    if (psi instanceof GoPackageDeclaration) return generatePackageBlock(node, styleSettings);

    if (psi instanceof GoBinaryExpression) {
      return new GoBinaryExpressionBlock(node, alignment, NO_WRAP, styleSettings);
    }

    if (psi instanceof GoFunctionDeclaration) {
      return new GoFunctionDeclarationBlock(node, alignment, indent, styleSettings);
    }

    IElementType elementType = node.getElementType();
    if (elementType == GoTokenTypes.pLPAREN) {
      return new GoLeafBlock(node, null, indent, NO_WRAP, styleSettings);
    } else if (elementType == GoTokenTypes.pRCURLY) {
      if (node.getTreeParent().getElementType() == GoElementTypes.LITERAL_COMPOSITE_VALUE) {
        boolean inFunctionCall = false;
        ASTNode nodeParent = node;
        while (nodeParent != null) {
          if (nodeParent.getElementType() == GoElementTypes.CALL_OR_CONVERSION_EXPRESSION) {
            int indentTabSize =
                styleSettings.getIndentOptions() == null
                    ? 4
                    : styleSettings.getIndentOptions().INDENT_SIZE;
            return new GoLeafBlock(
                node, null, Indent.getSpaceIndent(indentTabSize * -1), NO_WRAP, styleSettings);
          }

          nodeParent = nodeParent.getTreeParent();
        }
      }
    } else if (elementType == GoTokenTypes.kPACKAGE || elementType == GoTokenTypes.oSEMI) {
      return new GoLeafBlock(
          node,
          null,
          Indent.getAbsoluteNoneIndent(),
          Wrap.createWrap(WrapType.NONE, false),
          styleSettings);
    } else if (GoTokenTypeSets.COMMENTS.contains(elementType)) {
      return new GoLeafBlock(
          node, alignment, indent, Wrap.createWrap(WrapType.NONE, false), styleSettings);
    } else if (ALIGN_LIST_BLOCK_STATEMENTS.contains(elementType)) {
      return new GoAssignListBlock(node, alignment, indent, styleSettings);
    } else if (elementType == GoElementTypes.TYPE_STRUCT) {
      return new GoTypeStructBlock(node, alignment, indent, styleSettings);
      //        } else if (elementType == GoElementTypes.TYPE_INTERFACE) {
      //            return new GoTypeInterfaceBlock(node, alignment, indent, styleSettings);
    } else if (elementType == GoElementTypes.EXPRESSION_LIST) {
      return new GoExpressionListBlock(node, alignment, indent, styleSettings);
    } else if (elementType == GoElementTypes.UNARY_EXPRESSION) {
      return new GoUnaryExpressionBlock(node, alignment, indent, NO_WRAP, styleSettings);
    } else if (GoElementTypes.FUNCTION_CALL_SETS.contains(elementType)) {
      return new GoCallOrConvExpressionBlock(node, alignment, indent, NO_WRAP, styleSettings);
    } else if (elementType == GoElementTypes.PARENTHESISED_EXPRESSION) {
      return new GoParenthesisedExpressionBlock(node, alignment, indent, styleSettings);
    } else if (elementType == GoElementTypes.LABELED_STATEMENT) {
      return new GoLabeledStatmentBlock(node, styleSettings);
    } else if (elementType == GoElementTypes.FUNCTION_PARAMETER_LIST) {
      return new GoFunctionParameterListBlock(node, indent, styleSettings);
    } else if (elementType == GoElementTypes.FUNCTION_PARAMETER) {
      return new GoFunctionParameterBlock(node, indent, styleSettings);
    }

    return new GoBlock(node, alignment, indent, NO_WRAP, styleSettings);
  }
  public static class Config {
    private static final Alignment NO_ALIGNMENT = Alignment.createAlignment();
    private static final Wrap NO_WRAP = Wrap.createWrap(0, false);

    private Map<IElementType, Alignment> myAlignments = ContainerUtil.newHashMap();
    private Map<IElementType, Indent> myIndents = ContainerUtil.newHashMap();
    private Map<IElementType, Wrap> myWraps = ContainerUtil.newHashMap();

    private Map<IElementType, Condition<ASTNode>> myNoneAlignmentCondition =
        ContainerUtil.newHashMap();

    private Alignment myDefaultAlignment;
    private Indent myDefaultIndent;
    private Wrap myDefaultWrap;

    public ChildrenBlocksBuilder createBuilder() {
      return new ChildrenBlocksBuilder(this);
    }

    public Config setDefaultAlignment(Alignment alignment) {
      myDefaultAlignment = alignment;
      return this;
    }

    public Config setDefaultWrap(Wrap wrap) {
      myDefaultWrap = wrap;
      return this;
    }

    public Config setDefaultIndent(Indent indent) {
      myDefaultIndent = indent;
      return this;
    }

    public Config setAlignment(@NotNull IElementType elementType, @NotNull Alignment alignment) {
      myAlignments.put(elementType, alignment);
      return this;
    }

    public Config setNoAlignment(IElementType elementType) {
      myAlignments.put(elementType, NO_ALIGNMENT);
      return this;
    }

    public Config setNoAlignmentIf(
        IElementType elementType, Condition<ASTNode> applyAlignCondition) {
      myNoneAlignmentCondition.put(elementType, applyAlignCondition);
      return this;
    }

    public Config setIndent(IElementType elementType, Indent indent) {
      myIndents.put(elementType, indent);
      return this;
    }

    private Indent getIndent(IElementType elementType) {
      Indent indent = myIndents.get(elementType);
      return indent != null ? indent : myDefaultIndent;
    }

    private Alignment getAlignment(ASTNode node) {
      IElementType elementType = node.getElementType();

      Condition<ASTNode> noneAlignmentCondition = myNoneAlignmentCondition.get(elementType);
      if (noneAlignmentCondition != null && noneAlignmentCondition.value(node)) {
        return null;
      }

      Alignment alignment = myAlignments.get(elementType);
      if (alignment == null) {
        return myDefaultAlignment;
      }
      return alignment == NO_ALIGNMENT ? null : alignment;
    }

    private Wrap getWrap(IElementType elementType) {
      Wrap wrap = myWraps.get(elementType);
      if (wrap == NO_WRAP) return null;
      return wrap != null ? wrap : myDefaultWrap;
    }

    public Config setNoWrap(IElementType elementType) {
      myWraps.put(elementType, NO_WRAP);
      return this;
    }
  }