001/******************************************************************************* 002 * Copyright (c) 2017, 2018 Red Hat Inc 003 * All rights reserved. This program and the accompanying materials 004 * are made available under the terms of the Eclipse Public License v1.0 005 * which accompanies this distribution, and is available at 006 * http://www.eclipse.org/legal/epl-v10.html 007 * 008 * Contributors: 009 * Jens Reimann - initial API and implementation 010 *******************************************************************************/ 011package de.dentrassi.varlink.generator.util; 012 013import static org.eclipse.jdt.core.dom.Modifier.ModifierKeyword.PUBLIC_KEYWORD; 014 015import java.io.File; 016import java.io.Writer; 017import java.nio.charset.Charset; 018import java.nio.file.Files; 019import java.nio.file.Path; 020import java.util.List; 021import java.util.function.BiConsumer; 022 023import org.eclipse.jdt.core.ToolFactory; 024import org.eclipse.jdt.core.dom.AST; 025import org.eclipse.jdt.core.dom.ASTNode; 026import org.eclipse.jdt.core.dom.Assignment; 027import org.eclipse.jdt.core.dom.Block; 028import org.eclipse.jdt.core.dom.BodyDeclaration; 029import org.eclipse.jdt.core.dom.CompilationUnit; 030import org.eclipse.jdt.core.dom.FieldAccess; 031import org.eclipse.jdt.core.dom.FieldDeclaration; 032import org.eclipse.jdt.core.dom.MarkerAnnotation; 033import org.eclipse.jdt.core.dom.MethodDeclaration; 034import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; 035import org.eclipse.jdt.core.dom.NormalAnnotation; 036import org.eclipse.jdt.core.dom.PackageDeclaration; 037import org.eclipse.jdt.core.dom.ReturnStatement; 038import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 039import org.eclipse.jdt.core.dom.StringLiteral; 040import org.eclipse.jdt.core.dom.Type; 041import org.eclipse.jdt.core.dom.TypeDeclaration; 042import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 043import org.eclipse.jdt.core.formatter.CodeFormatter; 044import org.eclipse.jface.text.Document; 045import org.eclipse.text.edits.TextEdit; 046 047@SuppressWarnings("unchecked") 048public class JdtHelper { 049 050 public static StringLiteral newStringLiteral(final AST ast, final String value) { 051 final StringLiteral result = ast.newStringLiteral(); 052 result.setLiteralValue(value); 053 return result; 054 } 055 056 public static void make(final AST ast, final List<? super Object> decl, final ModifierKeyword... keywords) { 057 for (final ModifierKeyword keyword : keywords) { 058 decl.add(ast.newModifier(keyword)); 059 } 060 } 061 062 public static void make(final BodyDeclaration decl, final ModifierKeyword... keywords) { 063 make(decl.getAST(), decl.modifiers(), keywords); 064 } 065 066 public static void make(final SingleVariableDeclaration decl, final ModifierKeyword... keywords) { 067 make(decl.getAST(), decl.modifiers(), keywords); 068 } 069 070 public static void addSimpleAnnotation(final BodyDeclaration decl, final String name) { 071 final AST ast = decl.getAST(); 072 final MarkerAnnotation ann = ast.newMarkerAnnotation(); 073 ann.setTypeName(ast.newName(name)); 074 decl.modifiers().add(ann); 075 } 076 077 public static NormalAnnotation addAnnotation(final BodyDeclaration decl, final String name) { 078 final AST ast = decl.getAST(); 079 final NormalAnnotation ann = ast.newNormalAnnotation(); 080 ann.setTypeName(ast.newName(name)); 081 decl.modifiers().add(ann); 082 return ann; 083 } 084 085 public static void createCompilationUnit(final Path root, final String packageName, final String name, 086 final Charset charset, final BiConsumer<AST, CompilationUnit> consumer) { 087 088 final AST ast = AST.newAST(AST.JLS8); 089 090 final CompilationUnit cu = ast.newCompilationUnit(); 091 092 final PackageDeclaration pkg = ast.newPackageDeclaration(); 093 pkg.setName(ast.newName(packageName)); 094 cu.setPackage(pkg); 095 096 final Path path = root.resolve(packageName.replace(".", File.separator)).resolve(name + ".java"); 097 098 consumer.accept(ast, cu); 099 100 try { 101 Files.createDirectories(path.getParent()); 102 103 // format code 104 105 final CodeFormatter formatter = ToolFactory.createCodeFormatter(null); 106 final String s = cu.toString(); 107 final TextEdit result = formatter.format(CodeFormatter.K_COMPILATION_UNIT, s, 0, s.length(), 0, null); 108 109 final Document doc = new Document(s); 110 result.apply(doc); 111 112 // write out 113 114 try (final Writer writer = Files.newBufferedWriter(path, charset)) { 115 writer.append(doc.get()); 116 } 117 } catch (final Exception e) { 118 throw new RuntimeException(e); 119 } 120 121 } 122 123 public static void createField(final TypeDeclaration decl, final String typeName, final String fieldName, 124 final ModifierKeyword... keywords) { 125 126 final AST ast = decl.getAST(); 127 128 final VariableDeclarationFragment fragment = ast.newVariableDeclarationFragment(); 129 fragment.setName(ast.newSimpleName(fieldName)); 130 131 final FieldDeclaration fd = ast.newFieldDeclaration(fragment); 132 133 fd.setType(ast.newSimpleType(ast.newName(typeName))); 134 make(fd, keywords); 135 136 decl.bodyDeclarations().add(fd); 137 138 } 139 140 public static void createParameter(final MethodDeclaration decl, final Type type, final String name, 141 final ModifierKeyword... keywords) { 142 143 final AST ast = decl.getAST(); 144 145 final SingleVariableDeclaration svd = ast.newSingleVariableDeclaration(); 146 147 svd.setType(type); 148 svd.setName(ast.newSimpleName(name)); 149 make(svd, keywords); 150 151 decl.parameters().add(svd); 152 } 153 154 public static void createParameter(final MethodDeclaration decl, final String typeName, final String name, 155 final ModifierKeyword... keywords) { 156 final AST ast = decl.getAST(); 157 createParameter(decl, ast.newSimpleType(ast.newName(typeName)), name, keywords); 158 } 159 160 public static void createThisAssignment(final Block body, final String name) { 161 final AST ast = body.getAST(); 162 final Assignment as = ast.newAssignment(); 163 final FieldAccess fa = ast.newFieldAccess(); 164 fa.setExpression(ast.newThisExpression()); 165 fa.setName(ast.newSimpleName(name)); 166 as.setLeftHandSide(fa); 167 as.setRightHandSide(ast.newSimpleName(name)); 168 body.statements().add(ast.newExpressionStatement(as)); 169 } 170 171 public static <T extends ASTNode> T copyNode(final AST ast, final T node) { 172 return (T) ASTNode.copySubtree(ast, node); 173 } 174 175 public static MethodDeclaration createGetter(final AST ast, final Type type, final String name) { 176 final MethodDeclaration md = ast.newMethodDeclaration(); 177 md.setName(ast.newSimpleName("get" + Names.toUpperFirst(name))); 178 make(md, PUBLIC_KEYWORD); 179 180 md.setReturnType2(type); 181 182 final Block body = ast.newBlock(); 183 md.setBody(body); 184 185 final ReturnStatement ret = ast.newReturnStatement(); 186 body.statements().add(ret); 187 188 final FieldAccess fa = ast.newFieldAccess(); 189 fa.setExpression(ast.newThisExpression()); 190 fa.setName(ast.newSimpleName(name)); 191 ret.setExpression(fa); 192 193 return md; 194 } 195 196}