PrettyPrinterVisitor extends StandardVisitor { public static String prettyPrintAsString(IAstNode node) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); new PrettyPrinterVisitor(new PrintStream(bytes)).visit(node); return new String(bytes.toByteArray(), StandardCharsets.UTF_8); } PrettyPrinterVisitor(PrintStream out);  PrettyPrinterVisitor(PrintStream out,
                              int indentationWidth,
                              Supplier<String> newLineSupplier,
                              boolean emitGraphicsFuzzDefines,
                              Optional<String> license,
                              Optional<UniformValueSupplier> uniformValues); static String prettyPrintAsString(IAstNode node); static String prettyPrintAsString(IAstNode node, UniformValueSupplier uniformValues); static void emitShader(TranslationUnit shader,
                                Optional<String> license,
                                PrintStream stream,
                                int indentationWidth,
                                Supplier<String> newlineSupplier); static void emitShader(TranslationUnit shader,
                                Optional<String> license,
                                PrintStream stream,
                                int indentationWidth,
                                Supplier<String> newlineSupplier,
                                Optional<UniformValueSupplier> uniformValueSupplier); @Override void visitPrecisionDeclaration(PrecisionDeclaration precisionDeclaration); @Override void visitDeclarationStmt(DeclarationStmt declarationStmt); @Override void visitVariablesDeclaration(VariablesDeclaration variablesDeclaration); @Override void visitFunctionDefinition(FunctionDefinition functionDefinition); @Override void visitFunctionPrototype(FunctionPrototype functionPrototype); @Override void visitParameterDecl(ParameterDecl parameterDecl); @Override void visitBlockStmt(BlockStmt stmt); @Override void visitIfStmt(IfStmt ifStmt); @Override void visitBinaryExpr(BinaryExpr binaryExpr); @Override void visitParenExpr(ParenExpr parenExpr); @Override void visitVariableIdentifierExpr(VariableIdentifierExpr variableIdentifierExpr); @Override void visitUnaryExpr(UnaryExpr unaryExpr); @Override void visitMemberLookupExpr(MemberLookupExpr memberLookupExpr); @Override void visitIntConstantExpr(IntConstantExpr intConstantExpr); @Override void visitUIntConstantExpr(UIntConstantExpr intConstantExpr); @Override void visitFloatConstantExpr(FloatConstantExpr floatConstantExpr); @Override void visitBoolConstantExpr(BoolConstantExpr boolConstantExpr); @Override void visitBreakStmt(BreakStmt breakStmt); @Override void visitContinueStmt(ContinueStmt continueStmt); @Override void visitDiscardStmt(DiscardStmt discardStmt); @Override void visitReturnStmt(ReturnStmt returnStmt); @Override void visitExprStmt(ExprStmt exprStmt); @Override void visitFunctionCallExpr(FunctionCallExpr functionCallExpr); @Override void visitTypeConstructorExpr(TypeConstructorExpr typeConstructorExpr); @Override void visitQualifiedType(QualifiedType qualifiedType); @Override void visitBasicType(BasicType basicType); @Override void visitSamplerType(SamplerType samplerType); @Override void visitImageType(ImageType imageType); @Override void visitVoidType(VoidType voidType); @Override void visitAtomicIntType(AtomicIntType atomicIntType); @Override void visitNullStmt(NullStmt nullStmt); @Override void visitWhileStmt(WhileStmt whileStmt); @Override void visitForStmt(ForStmt forStmt); @Override void visitDoStmt(DoStmt doStmt); @Override void visitTernaryExpr(TernaryExpr ternaryExpr); @Override void visitArrayIndexExpr(ArrayIndexExpr arrayIndexExpr); @Override void visitStructNameType(StructNameType structNameType); @Override void visitArrayType(ArrayType arrayType); @Override void visitArrayConstructorExpr(ArrayConstructorExpr arrayConstructorExpr); @Override void visitStructDefinitionType(StructDefinitionType structDefinitionType); @Override void visitSwitchStmt(SwitchStmt switchStmt); @Override void visitDefaultCaseLabel(DefaultCaseLabel defaultCaseLabel); @Override void visitExprCaseLabel(ExprCaseLabel exprCaseLabel); @Override void visitInterfaceBlock(InterfaceBlock interfaceBlock); @Override void visitDefaultLayout(DefaultLayout defaultLayout); @Override void visitTranslationUnit(TranslationUnit translationUnit); @Override void visitPragmaStatement(PragmaStatement pragmaStatement); @Override void visitExtensionStatement(ExtensionStatement extensionStatement); @Override String toString(); static String defaultIndent(int level); static void emitGraphicsFuzzDefines(PrintStream out,
                                             ShadingLanguageVersion shadingLanguageVersion); static final int DEFAULT_INDENTATION_WIDTH; static final Supplier<String> DEFAULT_NEWLINE_SUPPLIER; }
@Test public void testUniformBlockContentsInComments() throws Exception { final String shaderWithBindings = "" + "layout(set = 0, binding = 0) uniform buf0 { int _GLF_uniform_int_values[2]; };" + "layout(set = 0, binding = 1) uniform buf1 { float _GLF_uniform_float_values[1]; };" + "void main() { }"; final String shaderPrettyPrinted = "" + "#define _int_0 _GLF_uniform_int_values[0]\n" + "#define _int_1 _GLF_uniform_int_values[1]\n" + "#define _float_3_0 _GLF_uniform_float_values[0]\n" + "\n" + " + "layout(set = 0, binding = 0) uniform buf0 {\n" + " int _GLF_uniform_int_values[2];\n" + "};\n" + " + "layout(set = 0, binding = 1) uniform buf1 {\n" + " float _GLF_uniform_float_values[1];\n" + "};\n" + "void main()\n" + "{\n" + "}\n"; UniformValueSupplier uniformValues = name -> { if (name.equals("_GLF_uniform_int_values")) { return Optional.of(Arrays.asList("0", "1")); } else if (name.equals("_GLF_uniform_float_values")) { return Optional.of(Arrays.asList("3.0")); } return Optional.empty(); }; assertEquals(shaderPrettyPrinted, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(shaderWithBindings), uniformValues)); }
@Test public void testUniformArrayContentsInComments() throws Exception { final String shader = "" + "uniform int a[3], b[2], X[1], Y[22], Z[1];" + "uniform float _GLF_uniform_float_values[3], D;" + "uniform uint _GLF_uniform_uint_values[2], E[33];" + "uniform int test[5], test2[1], A;" + "void main()" + "{" + " float a = _GLF_uniform_float_values[0];" + " float b = _GLF_uniform_float_values[1];" + " int c = _GLF_uniform_int_values[0];" + " int d = _GLF_uniform_int_values[1];" + " int e = _GLF_uniform_int_values[2];" + " int f = _GLF_uniform_uint_values[0];" + " int g = _GLF_uniform_uint_values[1];" + "}"; final String shaderPrettyPrinted = "" + "#define _uint_2 _GLF_uniform_uint_values[0]\n" + "#define _uint_11 _GLF_uniform_uint_values[1]\n" + "#define _uint_22 _GLF_uniform_uint_values[2]\n" + "#define _float_0_0 _GLF_uniform_float_values[0]\n" + "#define _float_1_4 _GLF_uniform_float_values[1]\n" + "#define _float_22_2 _GLF_uniform_float_values[2]\n" + "\n" + " + " + " + "uniform int a[3], b[2], X[1], Y[22], Z[1];\n" + "\n" + " + "uniform float _GLF_uniform_float_values[3], D;\n" + "\n" + " + "uniform uint _GLF_uniform_uint_values[2], E[33];\n" + "\n" + " + "uniform int test[5], test2[1], A;\n" + "\n" + "void main()\n" + "{\n" + " float a = _float_0_0;\n" + " float b = _float_1_4;\n" + " int c = _GLF_uniform_int_values[0];\n" + " int d = _GLF_uniform_int_values[1];\n" + " int e = _GLF_uniform_int_values[2];\n" + " int f = _uint_2;\n" + " int g = _uint_11;\n" + "}\n"; final List<TranslationUnit> shaders = new ArrayList<>(); shaders.add(ParseHelper.parse(shader, ShaderKind.FRAGMENT)); UniformValueSupplier uniformValues = name -> { if (name.equals("a")) { return Optional.of(Arrays.asList("0", "1", "2")); } else if (name.equals("b")) { return Optional.of(Arrays.asList("3", "4", "5")); } else if (name.equals("_GLF_uniform_uint_values")) { return Optional.of(Arrays.asList("2", "11", "22")); } else if (name.equals("_GLF_uniform_float_values")) { return Optional.of(Arrays.asList("0.0", "1.4", "22.2")); } else if (name.equals("test2")) { return Optional.of(Arrays.asList("66")); } else if (name.equals("Z")) { return Optional.of(Arrays.asList("77")); } return Optional.empty(); }; assertEquals(shaderPrettyPrinted, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(shader), uniformValues)); }
@Test public void testArraySizeExpressionInParameter() throws Exception { final String program = "" + "void foo(int A[3 + 4])\n" + "{\n" + "}\n" + "void main()\n" + "{\n" + " int a[7];\n" + " foo(a);\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintQualifiers() throws Exception { final String program = "" + "const volatile float x;\n\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintLayout() throws Exception { final String program = "" + "layout(location = 0) out vec4 color;\n\n" + "layout(anything=3, we, like=4, aswearenotyethandlingtheinternals) out vec2 blah;\n\n" + "void main()\n" + "{\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintComputeShader() throws Exception { final String program = "" + "layout(std430, binding = 2) buffer abuf {\n" + " int data[];\n" + "};\n" + "layout(local_size_x = 128, local_size_y = 1) in;\n" + "void main()\n" + "{\n" + " for(uint d = gl_WorkGroupSize.x / 2u; d > 0u; d >>= 1u)\n" + " {\n" + " if(gl_LocalInvocationID.x < d)\n" + " {\n" + " data[gl_LocalInvocationID.x] += data[d + gl_LocalInvocationID.x];\n" + " }\n" + " barrier();\n" + " }\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintStructs() throws Exception { final String program = "" + "struct S {\n" + " int a;\n" + " int b;\n" + "} ;\n" + "\n" + "struct T {\n" + " S myS1;\n" + " S myS2;\n" + "} ;\n" + "\n" + "void main()\n" + "{\n" + " T myT = T(S(1, 2), S(3, 4));\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintArrayParameter() throws Exception { final String program = "void foo(int A[2])\n" + "{\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintArrayVariable() throws Exception { final String program = "void main()\n" + "{\n" + " int A[2] = int[2](1, 2);\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintStructs2() throws Exception { final String program = "" + "struct S {\n" + " int a;\n" + " int b;\n" + "} ;\n" + "\n" + "S someS = S(8, 9);\n" + "\n" + "struct T {\n" + " S myS1;\n" + " S myS2;\n" + "} ;\n" + "\n" + "void main()\n" + "{\n" + " T myT = T(S(1, 2), S(3, 4));\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintStructs3() throws Exception { final String program = "" + "struct S {\n" + " int a;\n" + " int b;\n" + "} someS = S(8, 9);\n" + "\n" + "struct T {\n" + " S myS1;\n" + " S myS2;\n" + "} ;\n" + "\n" + "void main()\n" + "{\n" + " T myT = T(S(1, 2), S(someS.a, 4));\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintStructs4() throws Exception { final String program = "" + "struct {\n" + " int a;\n" + " int b;\n" + "} X, Y, Z;\n" + "\n" + "void main()\n" + "{\n" + " X.a = 3;\n" + " Y.b = X.a;\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintVersion() throws Exception { final String program = "#\tversion 100\nvoid main() { }\n"; final String expected = "#version 100\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintVersionEs() throws Exception { final String program = "#\tversion 320 es\nvoid main() { }\n"; final String expected = "#version 320 es\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintExtension() throws Exception { final String program = "" + "#\textension GL_EXT_gpu_shader5 : enable\nvoid main() { }"; final String expected = "" + "#extension GL_EXT_gpu_shader5 : enable\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintPragmaOptimizeOn() throws Exception { final String program = "#\tpragma optimize ( on )\nvoid main() { }\n"; final String expected = "#pragma optimize(on)\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintPragmaOptimizeOff() throws Exception { final String program = "#pragma optimize ( off )\nvoid main() { }\n"; final String expected = "#pragma optimize(off)\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintPragmaDebugOn() throws Exception { final String program = "#\tpragma debug ( on )\nvoid main() { }\n"; final String expected = "#pragma debug(on)\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintPragmaDebugOff() throws Exception { final String program = "#\tpragma debug ( off )\nvoid main() { }\n"; final String expected = "#pragma debug(off)\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintPragmaInvariantAll() throws Exception { final String program = "#\tpragma invariant ( all )\nvoid main() { }\n"; final String expected = "#pragma invariant(all)\nvoid main()\n{\n}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testSamplers() throws Exception { final String program = "uniform sampler1D s1;\n\n" + "uniform sampler2D s2;\n\n" + "uniform sampler2DRect s3;\n\n" + "uniform sampler3D s4;\n\n" + "uniform samplerCube s5;\n\n" + "uniform sampler1DShadow s7;\n\n" + "uniform sampler2DShadow s8;\n\n" + "uniform sampler2DRectShadow s9;\n\n" + "uniform samplerCubeShadow s10;\n\n" + "uniform sampler1DArray s11;\n\n" + "uniform sampler2DArray s12;\n\n" + "uniform sampler1DArrayShadow s13;\n\n" + "uniform sampler2DArrayShadow s14;\n\n" + "uniform samplerBuffer s15;\n\n" + "uniform samplerCubeArray s16;\n\n" + "uniform samplerCubeArrayShadow s17;\n\n" + "uniform isampler1D s18;\n\n" + "uniform isampler2D s19;\n\n" + "uniform isampler2DRect s20;\n\n" + "uniform isampler3D s21;\n\n" + "uniform isamplerCube s22;\n\n" + "uniform isampler1DArray s23;\n\n" + "uniform isampler2DArray s24;\n\n" + "uniform isamplerBuffer s25;\n\n" + "uniform isamplerCubeArray s26;\n\n" + "uniform usampler1D s27;\n\n" + "uniform usampler2D s28;\n\n" + "uniform usampler2DRect s29;\n\n" + "uniform usampler3D s30;\n\n" + "uniform usamplerCube s31;\n\n" + "uniform usampler1DArray s32;\n\n" + "uniform usampler2DArray s33;\n\n" + "uniform usamplerBuffer s34;\n\n" + "uniform usamplerCubeArray s35;\n\n" + "uniform sampler2DMS s36;\n\n" + "uniform isampler2DMS s37;\n\n" + "uniform usampler2DMS s38;\n\n" + "uniform sampler2DMSArray s39;\n\n" + "uniform isampler2DMSArray s40;\n\n" + "uniform usampler2DMSArray s41;\n\n"; final File shaderFile = temporaryFolder.newFile("shader.frag"); FileUtils.writeStringToFile(shaderFile, "#version 410\n\n" + program, StandardCharsets.UTF_8); assertEquals(0, ToolHelper.runValidatorOnShader(ExecHelper.RedirectType.TO_BUFFER, shaderFile).res); assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintVoidFormalParameter() throws Exception { final String program = "" + "int foo(void)\n" + "{\n" + " return 2;\n" + "}\n" + "void main(void)\n" + "{\n" + "}\n"; final String expected = "" + "int foo()\n" + "{\n" + " return 2;\n" + "}\n" + "void main()\n" + "{\n" + "}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintVoidActualParameter() throws Exception { final String program = "" + "void foo()\n" + "{\n" + " return 2;\n" + "}\n" + "void main()\n" + "{\n" + " foo(void);\n" + "}\n"; final String expected = "" + "void foo()\n" + "{\n" + " return 2;\n" + "}\n" + "void main()\n" + "{\n" + " foo();\n" + "}\n"; assertEquals(expected, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintLoopWithDeclarationsInside() throws Exception { final String program = "" + "void main()\n" + "{\n" + " for(int i = 0; i < 10; i ++)\n" + " {\n" + " int a;\n" + " int b;\n" + " }\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testParseAndPrintNestedLoop() throws Exception { final String program = "" + "void main()\n" + "{\n" + " for(int i = 0; i < 10; i ++)\n" + " {\n" + " for(int i = 0; i < 10; i ++)\n" + " {\n" + " int a;\n" + " int b;\n" + " }\n" + " }\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testArraySizeExpression() throws Exception { final String program = "" + "void main()\n" + "{\n" + " int a[3 + 4];\n" + "}\n"; assertEquals(program, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(program ))); }
@Test public void testLiteralUniformDefines() throws Exception { final String shaderWithBindings = "" + "layout(set = 0, binding = 0) uniform buf0 { int _GLF_uniform_int_values[2]; };" + "layout(set = 0, binding = 1) uniform buf1 { uint _GLF_uniform_uint_values[1]; };" + "layout(set = 0, binding = 2) uniform buf2 { float _GLF_uniform_float_values[3]; };" + "void main() { " + "int a = _GLF_uniform_int_values[0];" + "int b = _GLF_uniform_int_values[1];" + "uint c = _GLF_uniform_uint_values[0];" + "float d = _GLF_uniform_float_values[0];" + "float e = _GLF_uniform_float_values[1];" + "float f = _GLF_uniform_float_values[2];" + "}"; final String shaderPrettyPrinted = "" + "#define _int_0 _GLF_uniform_int_values[0]\n" + "#define _int_2 _GLF_uniform_int_values[1]\n" + "#define _uint_72 _GLF_uniform_uint_values[0]\n" + "#define _float_0_0 _GLF_uniform_float_values[0]\n" + "#define _float_22_4 _GLF_uniform_float_values[1]\n" + "#define _float_11_3 _GLF_uniform_float_values[2]\n" + "\n" + " + "layout(set = 0, binding = 0) uniform buf0 {\n" + " int _GLF_uniform_int_values[2];\n" + "};\n" + " + "layout(set = 0, binding = 1) uniform buf1 {\n" + " uint _GLF_uniform_uint_values[1];\n" + "};\n" + " + "layout(set = 0, binding = 2) uniform buf2 {\n" + " float _GLF_uniform_float_values[3];\n" + "};\n" + "void main()\n" + "{\n" + " int a = _int_0;\n" + " int b = _int_2;\n" + " uint c = _uint_72;\n" + " float d = _float_0_0;\n" + " float e = _float_22_4;\n" + " float f = _float_11_3;\n" + "}\n"; UniformValueSupplier uniformValues = name -> { if (name.equals("_GLF_uniform_int_values")) { return Optional.of(Arrays.asList("0", "2")); } else if (name.equals("_GLF_uniform_float_values")) { return Optional.of(Arrays.asList("0.0", "22.4", "11.3")); } else if (name.equals("_GLF_uniform_uint_values")) { return Optional.of(Arrays.asList("72")); } return Optional.empty(); }; assertEquals(shaderPrettyPrinted, PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(shaderWithBindings), uniformValues)); }