/*
* Copyright (c) 2016. Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.codegen.emitters;
import com.amazonaws.codegen.internal.Constants;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.TextEdit;
import java.util.HashMap;
import java.util.Map;
/**
* Formats the generated java source code. Uses Eclipse JDT core plugin from the Eclipse SDK.
*/
@SuppressWarnings("unchecked")
public class JavaCodeFormatter implements ContentProcessor {
private final CodeFormatter codeFormatter;
private static final Map<String, Object> DEFAULT_FORMATTER_OPTIONS;
static {
DEFAULT_FORMATTER_OPTIONS = DefaultCodeFormatterConstants.getEclipseDefaultSettings();
DEFAULT_FORMATTER_OPTIONS.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
DEFAULT_FORMATTER_OPTIONS.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_8);
DEFAULT_FORMATTER_OPTIONS.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
DEFAULT_FORMATTER_OPTIONS.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR,
JavaCore.SPACE);
DEFAULT_FORMATTER_OPTIONS.put(
DefaultCodeFormatterConstants.FORMATTER_COMMENT_INDENT_PARAMETER_DESCRIPTION,
DefaultCodeFormatterConstants.FALSE);
DEFAULT_FORMATTER_OPTIONS.put(
DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ENUM_CONSTANTS,
DefaultCodeFormatterConstants.createAlignmentValue(true,
DefaultCodeFormatterConstants.WRAP_ONE_PER_LINE,
DefaultCodeFormatterConstants.INDENT_ON_COLUMN));
DEFAULT_FORMATTER_OPTIONS.put(
DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_CONSTRUCTOR_DECLARATION,
DefaultCodeFormatterConstants.createAlignmentValue(false,
DefaultCodeFormatterConstants.WRAP_COMPACT,
DefaultCodeFormatterConstants.INDENT_DEFAULT));
// Formats custom file headers if provided
DEFAULT_FORMATTER_OPTIONS
.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HEADER,
DefaultCodeFormatterConstants.TRUE);
DEFAULT_FORMATTER_OPTIONS.put(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT, "160");
DEFAULT_FORMATTER_OPTIONS.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_LINE_LENGTH, "120");
}
/**
* Creates a JavaCodeFormatter using the default formatter options.
*/
public JavaCodeFormatter() {
this(new HashMap<>());
}
/**
* Creates a JavaCodeFormatter using the default formatter options and
* optionally applying user provided options on top.
*
* @param overrideOptions user provided options to apply on top of defaults
*/
public JavaCodeFormatter(final Map<String, Object> overrideOptions) {
Map formatterOptions = new HashMap<>(DEFAULT_FORMATTER_OPTIONS);
if (overrideOptions != null) {
formatterOptions.putAll(overrideOptions);
}
this.codeFormatter = ToolFactory.createCodeFormatter(formatterOptions,
ToolFactory.M_FORMAT_EXISTING);
}
public String apply(String contents) {
final TextEdit edit = codeFormatter.format(
CodeFormatter.K_COMPILATION_UNIT
| CodeFormatter.F_INCLUDE_COMMENTS, contents, 0,
contents.length(), 0, Constants.LINE_SEPARATOR);
if (edit == null) {
// TODO log a fatal or warning here. Throwing an exception is causing the actual freemarker error to be lost
return contents;
}
IDocument document = new Document(contents);
try {
edit.apply(document);
} catch (Exception e) {
throw new RuntimeException(
"Failed to format the generated source code.", e);
}
return document.get();
}
}