package org.archstudio.utils.eclipse.jdt; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.ToolFactory; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.ASTRequestor; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jdt.core.refactoring.CompilationUnitChange; import org.eclipse.jdt.internal.corext.fix.CleanUpConstants; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.ui.cleanup.CleanUpContext; import org.eclipse.jdt.ui.cleanup.CleanUpOptions; import org.eclipse.jdt.ui.cleanup.ICleanUp; import org.eclipse.jdt.ui.cleanup.ICleanUpFix; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.text.edits.TextEdit; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; import com.google.common.collect.Lists; import com.google.common.primitives.Ints; @SuppressWarnings({ "restriction", "unchecked" }) public class CodeGeneration { public static void formatCode(IProject project) throws CoreException { List<IFolder> folders = Lists.newArrayList(project.getFolder("src")); List<IFile> files = Lists.newArrayList(); while (folders.size() > 0) { IFolder f = folders.remove(folders.size() - 1); if (f.exists()) { for (IResource r : f.members()) { if (r instanceof IFile && "java".equalsIgnoreCase(((IFile) r).getFileExtension())) { files.add((IFile) r); } else if (r instanceof IFolder) { folders.add((IFolder) r); } } } } formatCode(project, files); } public static void formatCode(IFile file) throws CoreException { formatCode(file.getProject(), Arrays.asList(file)); } @SuppressWarnings("unused") private static void dump(Preferences preferences, int indent) throws BackingStoreException { char[] indentSpaceChars = new char[indent]; Arrays.fill(indentSpaceChars, ' '); String indentSpace = new String(indentSpaceChars); List<String> children = Arrays.asList(preferences.childrenNames()); Collections.sort(children); for (String child : children) { System.err.println(indentSpace + "* " + child); dump(preferences.node(child), indent + 2); } List<String> keys = Arrays.asList(preferences.keys()); Collections.sort(keys); for (String key : keys) { System.err.println(indentSpace + "- " + key + " = " + preferences.get(key, "[]")); } } public static void formatCode(IProject project, List<IFile> files) throws CoreException { Collection<ICompilationUnit> cus = Lists.newArrayList(); Collection<ICompilationUnit> cuWorkingCopies = Lists.newArrayList(); try { project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); IJavaProject javaProject = JavaCore.create(project); for (IFile file : files) { ICompilationUnit cu = JavaCore.createCompilationUnitFrom(file); cu = cu.getPrimary(); cu = cu.getWorkingCopy(new NullProgressMonitor()); if (cu.isWorkingCopy()) { cuWorkingCopies.add(cu); } cus.add(cu); } Map<String, String> compilerOptions = javaProject.getOptions(true); compilerOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7); compilerOptions.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7); compilerOptions.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7); compilerOptions.put(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION, JavaCore.WARNING); compilerOptions.put(JavaCore.COMPILER_PB_MISSING_OVERRIDE_ANNOTATION_FOR_INTERFACE_METHOD_IMPLEMENTATION, JavaCore.ENABLED); compilerOptions.put(JavaCore.COMPILER_PB_SUPPRESS_WARNINGS, JavaCore.DISABLED); compilerOptions.put(JavaCore.COMPILER_PB_SUPPRESS_OPTIONAL_ERRORS, JavaCore.DISABLED); compilerOptions.put(JavaCore.COMPILER_PB_MAX_PER_UNIT, "0"); CleanUpOptions cuOptions = JavaPlugin.getDefault().getCleanUpRegistry() .getDefaultOptions(CleanUpConstants.DEFAULT_SAVE_ACTION_OPTIONS); // dump(Platform.getPreferencesService().getRootNode(), 0); for (String key : Lists.newArrayList(cuOptions.getKeys())) { String value = Platform.getPreferencesService().getRootNode().node("instance") .node(JavaPlugin.getPluginId()).get(key, cuOptions.getValue(key)); cuOptions.setOption(key, value); } // iterate through cleanups { final List<ICleanUp> cleanups = Lists.newArrayList(JavaPlugin.getDefault().getCleanUpRegistry().createCleanUps()); for (final ICleanUp cleanup : cleanups) { try { final List<CleanUpContext> cleanupContexts = Lists.newArrayList(); cleanup.setOptions(cuOptions); RefactoringStatus status = cleanup.checkPreConditions(javaProject, cus.toArray(new ICompilationUnit[cus.size()]), new NullProgressMonitor()); if (status.isOK()) { if (cleanup.getRequirements().requiresAST()) { // AST.JLS4 is deprecated in Eclipse 4.5 @SuppressWarnings("all") ASTParser parser = ASTParser.newParser(AST.JLS4); parser.setProject(javaProject); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setResolveBindings(true); parser.setBindingsRecovery(true); parser.setStatementsRecovery(true); parser.setCompilerOptions(compilerOptions); parser.createASTs(cus.toArray(new ICompilationUnit[cus.size()]), new String[] {}, new ASTRequestor() { @Override public void acceptAST(ICompilationUnit source, CompilationUnit ast) { cleanupContexts.add(new CleanUpContext(source, ast)); } }, new NullProgressMonitor()); } else { for (ICompilationUnit source : cus) { cleanupContexts.add(new CleanUpContext(source, null)); } } for (CleanUpContext cleanupContext : cleanupContexts) { try { ICleanUpFix fix = cleanup.createFix(cleanupContext); if (fix != null) { CompilationUnitChange change = fix.createChange(new NullProgressMonitor()); if (change.isEnabled()) { TextEdit edit = change.getEdit(); if (edit != null) { cleanupContext.getCompilationUnit().applyTextEdit(edit, new NullProgressMonitor()); } } } } catch (Exception e) { e.printStackTrace(); } } cleanup.checkPostConditions(new NullProgressMonitor()); } } catch (Exception e) { e.printStackTrace(); } } } // format files { // dump(Platform.getPreferencesService().getRootNode(), 0); Map<String, String> formatterOptions = JavaCore.getOptions(); for (String key : Lists.newArrayList(formatterOptions.keySet())) { String value = Platform.getPreferencesService().getRootNode().node("project") .node(project.getName()).node("org.eclipse.jdt.core").get(key, formatterOptions.get(key)); formatterOptions.put(key, value); } CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(formatterOptions, ToolFactory.M_FORMAT_NEW); for (ICompilationUnit cu : cus) { String contents = cu.getBuffer().getContents(); for (int kind : Ints.asList(CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS)) { TextEdit edit = codeFormatter.format(kind, contents, 0, contents.length(), 0, null); if (edit != null) { cu.applyTextEdit(edit, new NullProgressMonitor()); } } } } // save files for (ICompilationUnit cu : cus) { cu.commitWorkingCopy(true, new NullProgressMonitor()); cu.save(new NullProgressMonitor(), true); } } catch (Exception e) { throw new CoreException( new Status(IStatus.ERROR, "org.archstudio.utils.eclipse.formatcode", e.getMessage(), e)); } finally { for (ICompilationUnit cu : cuWorkingCopies) { cu.discardWorkingCopy(); } } } }