You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/05/14 10:53:31 UTC
[48/51] [partial] incubator-freemarker git commit: Migrated from Ant
to Gradle, and modularized the project. This is an incomplete migration;
there are some TODO-s in the build scripts, and release related tasks are
still missing. What works: Building th
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/ide-settings/Eclipse/Formatter-profile-FreeMarker.xml
----------------------------------------------------------------------
diff --git a/freemarker-core/src/ide-settings/Eclipse/Formatter-profile-FreeMarker.xml b/freemarker-core/src/ide-settings/Eclipse/Formatter-profile-FreeMarker.xml
new file mode 100644
index 0000000..2070004
--- /dev/null
+++ b/freemarker-core/src/ide-settings/Eclipse/Formatter-profile-FreeMarker.xml
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License 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.
+-->
+<profiles version="12">
+<profile kind="CodeFormatterProfile" name="FreeMarker" version="12">
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+</profile>
+</profiles>
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/ide-settings/IntelliJ-IDEA/Editor-Inspections-FreeMarker.xml
----------------------------------------------------------------------
diff --git a/freemarker-core/src/ide-settings/IntelliJ-IDEA/Editor-Inspections-FreeMarker.xml b/freemarker-core/src/ide-settings/IntelliJ-IDEA/Editor-Inspections-FreeMarker.xml
new file mode 100644
index 0000000..4b40e57
--- /dev/null
+++ b/freemarker-core/src/ide-settings/IntelliJ-IDEA/Editor-Inspections-FreeMarker.xml
@@ -0,0 +1,33 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License 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.
+-->
+<component name="InspectionProjectProfileManager">
+ <profile version="1.0">
+ <option name="myName" value="FreeMarker" />
+ <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
+ <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
+ <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
+ </inspection_tool>
+ <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true">
+ <option name="ignoreObjectMethods" value="true" />
+ <option name="ignoreAnonymousClassMethods" value="false" />
+ </inspection_tool>
+ <inspection_tool class="RawTypeCanBeGeneric" enabled="true" level="WARNING" enabled_by_default="true" />
+ <inspection_tool class="RawUseOfParameterizedType" enabled="true" level="WARNING" enabled_by_default="true" />
+ </profile>
+</component>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/ide-settings/IntelliJ-IDEA/Java-code-style-FreeMarker.xml
----------------------------------------------------------------------
diff --git a/freemarker-core/src/ide-settings/IntelliJ-IDEA/Java-code-style-FreeMarker.xml b/freemarker-core/src/ide-settings/IntelliJ-IDEA/Java-code-style-FreeMarker.xml
new file mode 100644
index 0000000..983f742
--- /dev/null
+++ b/freemarker-core/src/ide-settings/IntelliJ-IDEA/Java-code-style-FreeMarker.xml
@@ -0,0 +1,66 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License 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.
+-->
+<code_scheme name="FreeMarker">
+ <option name="LINE_SEPARATOR" value="
" />
+ <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
+ <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1" />
+ <option name="IMPORT_LAYOUT_TABLE">
+ <value>
+ <package name="" withSubpackages="true" static="true" />
+ <emptyLine />
+ <package name="java" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="javax" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="org" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="com" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="" withSubpackages="true" static="false" />
+ <emptyLine />
+ </value>
+ </option>
+ <option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
+ <option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
+ <option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
+ <option name="JD_KEEP_EMPTY_PARAMETER" value="false" />
+ <option name="JD_KEEP_EMPTY_EXCEPTION" value="false" />
+ <option name="JD_KEEP_EMPTY_RETURN" value="false" />
+ <option name="JD_PARAM_DESCRIPTION_ON_NEW_LINE" value="true" />
+ <option name="WRAP_COMMENTS" value="true" />
+ <JavaCodeStyleSettings>
+ <option name="ANNOTATION_PARAMETER_WRAP" value="1" />
+ <option name="CLASS_NAMES_IN_JAVADOC" value="3" />
+ </JavaCodeStyleSettings>
+ <codeStyleSettings language="JAVA">
+ <option name="RIGHT_MARGIN" value="120" />
+ <option name="CALL_PARAMETERS_WRAP" value="1" />
+ <option name="EXTENDS_LIST_WRAP" value="1" />
+ <option name="THROWS_LIST_WRAP" value="1" />
+ <option name="EXTENDS_KEYWORD_WRAP" value="1" />
+ <option name="BINARY_OPERATION_WRAP" value="1" />
+ <option name="TERNARY_OPERATION_WRAP" value="1" />
+ <option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
+ <option name="ARRAY_INITIALIZER_WRAP" value="1" />
+ <option name="ASSIGNMENT_WRAP" value="1" />
+ <option name="WRAP_LONG_LINES" value="true" />
+ <option name="PARAMETER_ANNOTATION_WRAP" value="1" />
+ <option name="VARIABLE_ANNOTATION_WRAP" value="1" />
+ </codeStyleSettings>
+</code_scheme>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/APINotSupportedTemplateException.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/APINotSupportedTemplateException.java b/freemarker-core/src/main/java/org/apache/freemarker/core/APINotSupportedTemplateException.java
new file mode 100644
index 0000000..732f5e2
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/APINotSupportedTemplateException.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import org.apache.freemarker.core.model.TemplateModel;
+
+/**
+ * Thrown when {@code ?api} is not supported by a value.
+ */
+class APINotSupportedTemplateException extends TemplateException {
+
+ APINotSupportedTemplateException(Environment env, ASTExpression blamedExpr, TemplateModel model) {
+ super(null, env, blamedExpr, buildDescription(env, blamedExpr, model));
+ }
+
+ protected static _ErrorDescriptionBuilder buildDescription(Environment env, ASTExpression blamedExpr,
+ TemplateModel tm) {
+ final _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder(
+ "The value doesn't support ?api. See requirements in the FreeMarker Manual. ("
+ + "FTL type: ", new _DelayedFTLTypeDescription(tm),
+ ", TemplateModel class: ", new _DelayedShortClassName(tm.getClass()),
+ ", ObjectWapper: ", new _DelayedToString(env.getObjectWrapper()), ")"
+ ).blame(blamedExpr);
+
+ if (blamedExpr.isLiteral()) {
+ desc.tip("Only adapted Java objects can possibly have API, not values created inside templates.");
+ }
+
+ return desc;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java
new file mode 100644
index 0000000..7ee2695
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTComment.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import org.apache.freemarker.core.util._StringUtil;
+
+/**
+ * AST comment node
+ */
+final class ASTComment extends ASTElement {
+
+ private final String text;
+
+ ASTComment(String text) {
+ this.text = text;
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) {
+ // do nothing, skip the body
+ return null;
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ if (canonical) {
+ return "<#--" + text + "-->";
+ } else {
+ return "comment " + _StringUtil.jQuote(text.trim());
+ }
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return "#--...--";
+ }
+
+
+ @Override
+ int getParameterCount() {
+ return 1;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ if (idx != 0) throw new IndexOutOfBoundsException();
+ return text;
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ if (idx != 0) throw new IndexOutOfBoundsException();
+ return ParameterRole.CONTENT;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ @Override
+ boolean isOutputCacheable() {
+ return true;
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java
new file mode 100644
index 0000000..fe42f41
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDebugBreak.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+import org.apache.freemarker.core.debug._DebuggerService;
+
+/**
+ * AST node: A debug breakpoint
+ */
+class ASTDebugBreak extends ASTElement {
+ public ASTDebugBreak(ASTElement nestedBlock) {
+ addChild(nestedBlock);
+ copyLocationFrom(nestedBlock);
+ }
+
+ @Override
+ protected ASTElement[] accept(Environment env) throws TemplateException, IOException {
+ if (!_DebuggerService.suspendEnvironment(
+ env, getTemplate().getSourceName(), getChild(0).getBeginLine())) {
+ return getChild(0).accept(env);
+ } else {
+ throw new StopException(env, "Stopped by debugger");
+ }
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ if (canonical) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("<#-- ");
+ sb.append("debug break");
+ if (getChildCount() == 0) {
+ sb.append(" /-->");
+ } else {
+ sb.append(" -->");
+ sb.append(getChild(0).getCanonicalForm());
+ sb.append("<#--/ debug break -->");
+ }
+ return sb.toString();
+ } else {
+ return "debug break";
+ }
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return "#debug_break";
+ }
+
+ @Override
+ int getParameterCount() {
+ return 0;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java
new file mode 100644
index 0000000..4961f7f
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignment.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateNumberModel;
+import org.apache.freemarker.core.util.BugException;
+import org.apache.freemarker.core.util._StringUtil;
+
+/**
+ * AST directive node: An instruction that makes a single assignment, like {@code <#local x=1>}, {@code <#global x=1>},
+ * {@code <#assign x=1>}.
+ * This is also used as the child of {@link ASTDirAssignmentsContainer}, if there are multiple assignments in the same
+ * tag, like in {@code <#local x=1 y=2>}.
+ */
+final class ASTDirAssignment extends ASTDirective {
+
+ // These must not clash with ArithmeticExpression.TYPE_... constants:
+ private static final int OPERATOR_TYPE_EQUALS = 0x10000;
+ private static final int OPERATOR_TYPE_PLUS_EQUALS = 0x10001;
+ private static final int OPERATOR_TYPE_PLUS_PLUS = 0x10002;
+ private static final int OPERATOR_TYPE_MINUS_MINUS = 0x10003;
+
+ private final int/*enum*/ scope;
+ private final String variableName;
+ private final int operatorType;
+ private final ASTExpression valueExp;
+ private ASTExpression namespaceExp;
+
+ static final int NAMESPACE = 1;
+ static final int LOCAL = 2;
+ static final int GLOBAL = 3;
+
+ private static final Number ONE = Integer.valueOf(1);
+
+ /**
+ * @param variableName the variable name to assign to.
+ * @param valueExp the expression to assign.
+ * @param scope the scope of the assignment, one of NAMESPACE, LOCAL, or GLOBAL
+ */
+ ASTDirAssignment(String variableName,
+ int operator,
+ ASTExpression valueExp,
+ int scope) {
+ this.scope = scope;
+
+ this.variableName = variableName;
+
+ if (operator == FMParserConstants.EQUALS) {
+ operatorType = OPERATOR_TYPE_EQUALS;
+ } else {
+ switch (operator) {
+ case FMParserConstants.PLUS_PLUS:
+ operatorType = OPERATOR_TYPE_PLUS_PLUS;
+ break;
+ case FMParserConstants.MINUS_MINUS:
+ operatorType = OPERATOR_TYPE_MINUS_MINUS;
+ break;
+ case FMParserConstants.PLUS_EQUALS:
+ operatorType = OPERATOR_TYPE_PLUS_EQUALS;
+ break;
+ case FMParserConstants.MINUS_EQUALS:
+ operatorType = ArithmeticExpression.TYPE_SUBSTRACTION;
+ break;
+ case FMParserConstants.TIMES_EQUALS:
+ operatorType = ArithmeticExpression.TYPE_MULTIPLICATION;
+ break;
+ case FMParserConstants.DIV_EQUALS:
+ operatorType = ArithmeticExpression.TYPE_DIVISION;
+ break;
+ case FMParserConstants.MOD_EQUALS:
+ operatorType = ArithmeticExpression.TYPE_MODULO;
+ break;
+ default:
+ throw new BugException();
+ }
+ }
+
+ this.valueExp = valueExp;
+ }
+
+ void setNamespaceExp(ASTExpression namespaceExp) {
+ if (scope != NAMESPACE && namespaceExp != null) throw new BugException();
+ this.namespaceExp = namespaceExp;
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) throws TemplateException {
+ final Environment.Namespace namespace;
+ if (namespaceExp == null) {
+ switch (scope) {
+ case LOCAL:
+ namespace = null;
+ break;
+ case GLOBAL:
+ namespace = env.getGlobalNamespace();
+ break;
+ case NAMESPACE:
+ namespace = env.getCurrentNamespace();
+ break;
+ default:
+ throw new BugException("Unexpected scope type: " + scope);
+ }
+ } else {
+ TemplateModel namespaceTM = namespaceExp.eval(env);
+ try {
+ namespace = (Environment.Namespace) namespaceTM;
+ } catch (ClassCastException e) {
+ throw new NonNamespaceException(namespaceExp, namespaceTM, env);
+ }
+ if (namespace == null) {
+ throw InvalidReferenceException.getInstance(namespaceExp, env);
+ }
+ }
+
+ TemplateModel value;
+ if (operatorType == OPERATOR_TYPE_EQUALS) {
+ value = valueExp.eval(env);
+ valueExp.assertNonNull(value, env);
+ } else {
+ TemplateModel lhoValue;
+ if (namespace == null) {
+ lhoValue = env.getLocalVariable(variableName);
+ } else {
+ lhoValue = namespace.get(variableName);
+ }
+
+ if (operatorType == OPERATOR_TYPE_PLUS_EQUALS) { // Add or concat operation
+ if (lhoValue == null) {
+ throw InvalidReferenceException.getInstance(
+ variableName, getOperatorTypeAsString(), env);
+ }
+
+ value = valueExp.eval(env);
+ valueExp.assertNonNull(value, env);
+ value = ASTExpAddOrConcat._eval(env, namespaceExp, null, lhoValue, valueExp, value);
+ } else { // Numerical operation
+ Number lhoNumber;
+ if (lhoValue instanceof TemplateNumberModel) {
+ lhoNumber = _EvalUtil.modelToNumber((TemplateNumberModel) lhoValue, null);
+ } else if (lhoValue == null) {
+ throw InvalidReferenceException.getInstance(variableName, getOperatorTypeAsString(), env);
+ } else {
+ throw new NonNumericalException(variableName, lhoValue, null, env);
+ }
+
+ if (operatorType == OPERATOR_TYPE_PLUS_PLUS) {
+ value = ASTExpAddOrConcat._evalOnNumbers(env, getParent(), lhoNumber, ONE);
+ } else if (operatorType == OPERATOR_TYPE_MINUS_MINUS) {
+ value = ArithmeticExpression._eval(
+ env, getParent(), lhoNumber, ArithmeticExpression.TYPE_SUBSTRACTION, ONE);
+ } else { // operatorType == ArithmeticExpression.TYPE_...
+ Number rhoNumber = valueExp.evalToNumber(env);
+ value = ArithmeticExpression._eval(env, this, lhoNumber, operatorType, rhoNumber);
+ }
+ }
+ }
+
+ if (namespace == null) {
+ env.setLocalVariable(variableName, value);
+ } else {
+ namespace.put(variableName, value);
+ }
+ return null;
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ StringBuilder buf = new StringBuilder();
+ String dn = getParent() instanceof ASTDirAssignmentsContainer ? null : getNodeTypeSymbol();
+ if (dn != null) {
+ if (canonical) buf.append("<");
+ buf.append(dn);
+ buf.append(' ');
+ }
+
+ buf.append(_StringUtil.toFTLTopLevelTragetIdentifier(variableName));
+
+ if (valueExp != null) {
+ buf.append(' ');
+ }
+ buf.append(getOperatorTypeAsString());
+ if (valueExp != null) {
+ buf.append(' ');
+ buf.append(valueExp.getCanonicalForm());
+ }
+ if (dn != null) {
+ if (namespaceExp != null) {
+ buf.append(" in ");
+ buf.append(namespaceExp.getCanonicalForm());
+ }
+ if (canonical) buf.append(">");
+ }
+ return buf.toString();
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return getDirectiveName(scope);
+ }
+
+ static String getDirectiveName(int scope) {
+ if (scope == ASTDirAssignment.LOCAL) {
+ return "#local";
+ } else if (scope == ASTDirAssignment.GLOBAL) {
+ return "#global";
+ } else if (scope == ASTDirAssignment.NAMESPACE) {
+ return "#assign";
+ } else {
+ return "#{unknown_assignment_type}";
+ }
+ }
+
+ @Override
+ int getParameterCount() {
+ return 5;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ switch (idx) {
+ case 0: return variableName;
+ case 1: return getOperatorTypeAsString();
+ case 2: return valueExp;
+ case 3: return Integer.valueOf(scope);
+ case 4: return namespaceExp;
+ default: throw new IndexOutOfBoundsException();
+ }
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ switch (idx) {
+ case 0: return ParameterRole.ASSIGNMENT_TARGET;
+ case 1: return ParameterRole.ASSIGNMENT_OPERATOR;
+ case 2: return ParameterRole.ASSIGNMENT_SOURCE;
+ case 3: return ParameterRole.VARIABLE_SCOPE;
+ case 4: return ParameterRole.NAMESPACE;
+ default: throw new IndexOutOfBoundsException();
+ }
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+ private String getOperatorTypeAsString() {
+ if (operatorType == OPERATOR_TYPE_EQUALS) {
+ return "=";
+ } else if (operatorType == OPERATOR_TYPE_PLUS_EQUALS) {
+ return "+=";
+ } else if (operatorType == OPERATOR_TYPE_PLUS_PLUS) {
+ return "++";
+ } else if (operatorType == OPERATOR_TYPE_MINUS_MINUS) {
+ return "--";
+ } else {
+ return ArithmeticExpression.getOperatorSymbol(operatorType) + "=";
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java
new file mode 100644
index 0000000..fd2873d
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAssignmentsContainer.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+/**
+ * AST directive node: An instruction that does multiple assignments, like [#local x=1 x=2].
+ * Each assignment is represented by a {@link ASTDirAssignment} child element.
+ * If there's only one assignment, its usually just a {@link ASTDirAssignment} without parent {@link ASTDirAssignmentsContainer}.
+ */
+final class ASTDirAssignmentsContainer extends ASTDirective {
+
+ private int scope;
+ private ASTExpression namespaceExp;
+
+ ASTDirAssignmentsContainer(int scope) {
+ this.scope = scope;
+ setChildBufferCapacity(1);
+ }
+
+ void addAssignment(ASTDirAssignment assignment) {
+ addChild(assignment);
+ }
+
+ void setNamespaceExp(ASTExpression namespaceExp) {
+ this.namespaceExp = namespaceExp;
+ int ln = getChildCount();
+ for (int i = 0; i < ln; i++) {
+ ((ASTDirAssignment) getChild(i)).setNamespaceExp(namespaceExp);
+ }
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) throws TemplateException, IOException {
+ return getChildBuffer();
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ StringBuilder buf = new StringBuilder();
+ if (canonical) buf.append('<');
+ buf.append(ASTDirAssignment.getDirectiveName(scope));
+ if (canonical) {
+ buf.append(' ');
+ int ln = getChildCount();
+ for (int i = 0; i < ln; i++) {
+ if (i != 0) {
+ buf.append(", ");
+ }
+ ASTDirAssignment assignment = (ASTDirAssignment) getChild(i);
+ buf.append(assignment.getCanonicalForm());
+ }
+ } else {
+ buf.append("-container");
+ }
+ if (namespaceExp != null) {
+ buf.append(" in ");
+ buf.append(namespaceExp.getCanonicalForm());
+ }
+ if (canonical) buf.append(">");
+ return buf.toString();
+ }
+
+ @Override
+ int getParameterCount() {
+ return 2;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ switch (idx) {
+ case 0: return Integer.valueOf(scope);
+ case 1: return namespaceExp;
+ default: return null;
+ }
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ switch (idx) {
+ case 0: return ParameterRole.VARIABLE_SCOPE;
+ case 1: return ParameterRole.NAMESPACE;
+ default: return null;
+ }
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return ASTDirAssignment.getDirectiveName(scope);
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java
new file mode 100644
index 0000000..c01c453
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAttemptRecoverContainer.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+/**
+ * AST directive node: Holder for the attempted section of the {@code #attempt} element and of the nested
+ * {@code #recover} element ({@link ASTDirRecover}).
+ */
+final class ASTDirAttemptRecoverContainer extends ASTDirective {
+
+ private ASTElement attemptedSection;
+ private ASTDirRecover recoverySection;
+
+ ASTDirAttemptRecoverContainer(TemplateElements attemptedSectionChildren, ASTDirRecover recoverySection) {
+ ASTElement attemptedSection = attemptedSectionChildren.asSingleElement();
+ this.attemptedSection = attemptedSection;
+ this.recoverySection = recoverySection;
+ setChildBufferCapacity(2);
+ addChild(attemptedSection); // for backward compatibility
+ addChild(recoverySection);
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) throws TemplateException, IOException {
+ env.visitAttemptRecover(this, attemptedSection, recoverySection);
+ return null;
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ if (!canonical) {
+ return getNodeTypeSymbol();
+ } else {
+ StringBuilder buf = new StringBuilder();
+ buf.append("<").append(getNodeTypeSymbol()).append(">");
+ buf.append(getChildrenCanonicalForm());
+ buf.append("</").append(getNodeTypeSymbol()).append(">");
+ return buf.toString();
+ }
+ }
+
+ @Override
+ int getParameterCount() {
+ return 1;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ if (idx != 0) throw new IndexOutOfBoundsException();
+ return recoverySection;
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ if (idx != 0) throw new IndexOutOfBoundsException();
+ return ParameterRole.ERROR_HANDLER;
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return "#attempt";
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java
new file mode 100644
index 0000000..b27dc0a
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirAutoEsc.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+/**
+ * AST directive node: {@code #autoEsc}
+ */
+final class ASTDirAutoEsc extends ASTDirective {
+
+ ASTDirAutoEsc(TemplateElements children) {
+ setChildren(children);
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) throws TemplateException, IOException {
+ return getChildBuffer();
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ if (canonical) {
+ return "<" + getNodeTypeSymbol() + "\">" + getChildrenCanonicalForm() + "</" + getNodeTypeSymbol() + ">";
+ } else {
+ return getNodeTypeSymbol();
+ }
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return "#autoesc";
+ }
+
+ @Override
+ int getParameterCount() {
+ return 0;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ boolean isIgnorable(boolean stripWhitespace) {
+ return getChildCount() == 0;
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java
new file mode 100644
index 0000000..19a0c25
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirBreak.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+/**
+ * AST directive node: {@code #break}
+ */
+final class ASTDirBreak extends ASTDirective {
+
+ @Override
+ ASTElement[] accept(Environment env) {
+ throw Break.INSTANCE;
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ return canonical ? "<" + getNodeTypeSymbol() + "/>" : getNodeTypeSymbol();
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return "#break";
+ }
+
+ @Override
+ int getParameterCount() {
+ return 0;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ static class Break extends RuntimeException {
+ static final Break INSTANCE = new Break();
+ private Break() {
+ }
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
new file mode 100644
index 0000000..9aa5eab
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCapturingAssignment.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.model.TemplateModelException;
+import org.apache.freemarker.core.model.TemplateTransformModel;
+import org.apache.freemarker.core.model.impl.SimpleScalar;
+import org.apache.freemarker.core.outputformat.MarkupOutputFormat;
+
+/**
+ * AST directive node: Like {@code <#local x>...</#local>}.
+ */
+final class ASTDirCapturingAssignment extends ASTDirective {
+
+ private final String varName;
+ private final ASTExpression namespaceExp;
+ private final int scope;
+ private final MarkupOutputFormat<?> markupOutputFormat;
+
+ ASTDirCapturingAssignment(TemplateElements children, String varName, int scope, ASTExpression namespaceExp, MarkupOutputFormat<?> markupOutputFormat) {
+ setChildren(children);
+ this.varName = varName;
+ this.namespaceExp = namespaceExp;
+ this.scope = scope;
+ this.markupOutputFormat = markupOutputFormat;
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) throws TemplateException, IOException {
+ ASTElement[] children = getChildBuffer();
+ if (children != null) {
+ env.visitAndTransform(children, new CaptureOutput(env), null);
+ } else {
+ TemplateModel value = capturedStringToModel("");
+ if (namespaceExp != null) {
+ Environment.Namespace ns = (Environment.Namespace) namespaceExp.eval(env);
+ ns.put(varName, value);
+ } else if (scope == ASTDirAssignment.NAMESPACE) {
+ env.setVariable(varName, value);
+ } else if (scope == ASTDirAssignment.GLOBAL) {
+ env.setGlobalVariable(varName, value);
+ } else if (scope == ASTDirAssignment.LOCAL) {
+ env.setLocalVariable(varName, value);
+ }
+ }
+ return null;
+ }
+
+ private TemplateModel capturedStringToModel(String s) throws TemplateModelException {
+ return markupOutputFormat == null ? new SimpleScalar(s) : markupOutputFormat.fromMarkup(s);
+ }
+
+ private class CaptureOutput implements TemplateTransformModel {
+ private final Environment env;
+ private final Environment.Namespace fnsModel;
+
+ CaptureOutput(Environment env) throws TemplateException {
+ this.env = env;
+ TemplateModel nsModel = null;
+ if (namespaceExp != null) {
+ nsModel = namespaceExp.eval(env);
+ if (!(nsModel instanceof Environment.Namespace)) {
+ throw new NonNamespaceException(namespaceExp, nsModel, env);
+ }
+ }
+ fnsModel = (Environment.Namespace ) nsModel;
+ }
+
+ @Override
+ public Writer getWriter(Writer out, Map args) {
+ return new StringWriter() {
+ @Override
+ public void close() throws IOException {
+ TemplateModel result;
+ try {
+ result = capturedStringToModel(toString());
+ } catch (TemplateModelException e) {
+ // [Java 1.6] e to cause
+ throw new IOException("Failed to invoke FTL value from captured string: " + e);
+ }
+ switch(scope) {
+ case ASTDirAssignment.NAMESPACE: {
+ if (fnsModel != null) {
+ fnsModel.put(varName, result);
+ } else {
+ env.setVariable(varName, result);
+ }
+ break;
+ }
+ case ASTDirAssignment.LOCAL: {
+ env.setLocalVariable(varName, result);
+ break;
+ }
+ case ASTDirAssignment.GLOBAL: {
+ env.setGlobalVariable(varName, result);
+ break;
+ }
+ }
+ }
+ };
+ }
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ StringBuilder sb = new StringBuilder();
+ if (canonical) sb.append("<");
+ sb.append(getNodeTypeSymbol());
+ sb.append(' ');
+ sb.append(varName);
+ if (namespaceExp != null) {
+ sb.append(" in ");
+ sb.append(namespaceExp.getCanonicalForm());
+ }
+ if (canonical) {
+ sb.append('>');
+ sb.append(getChildrenCanonicalForm());
+ sb.append("</");
+ sb.append(getNodeTypeSymbol());
+ sb.append('>');
+ } else {
+ sb.append(" = .nested_output");
+ }
+ return sb.toString();
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return ASTDirAssignment.getDirectiveName(scope);
+ }
+
+ @Override
+ int getParameterCount() {
+ return 3;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ switch (idx) {
+ case 0: return varName;
+ case 1: return Integer.valueOf(scope);
+ case 2: return namespaceExp;
+ default: throw new IndexOutOfBoundsException();
+ }
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ switch (idx) {
+ case 0: return ParameterRole.ASSIGNMENT_TARGET;
+ case 1: return ParameterRole.VARIABLE_SCOPE;
+ case 2: return ParameterRole.NAMESPACE;
+ default: throw new IndexOutOfBoundsException();
+ }
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java
new file mode 100644
index 0000000..0f87778
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCase.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+/**
+ * AST directive node: {@code #case} (inside a {@code #switch})
+ */
+final class ASTDirCase extends ASTDirective {
+
+ final int TYPE_CASE = 0;
+ final int TYPE_DEFAULT = 1;
+
+ ASTExpression condition;
+
+ ASTDirCase(ASTExpression matchingValue, TemplateElements children) {
+ condition = matchingValue;
+ setChildren(children);
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) {
+ return getChildBuffer();
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ StringBuilder sb = new StringBuilder();
+ if (canonical) sb.append('<');
+ sb.append(getNodeTypeSymbol());
+ if (condition != null) {
+ sb.append(' ');
+ sb.append(condition.getCanonicalForm());
+ }
+ if (canonical) {
+ sb.append('>');
+ sb.append(getChildrenCanonicalForm());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return condition != null ? "#case" : "#default";
+ }
+
+ @Override
+ int getParameterCount() {
+ return 2;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ switch (idx) {
+ case 0: return condition;
+ case 1: return Integer.valueOf(condition != null ? TYPE_CASE : TYPE_DEFAULT);
+ default: throw new IndexOutOfBoundsException();
+ }
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ switch (idx) {
+ case 0: return ParameterRole.CONDITION;
+ case 1: return ParameterRole.AST_NODE_SUBTYPE;
+ default: throw new IndexOutOfBoundsException();
+ }
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java
new file mode 100644
index 0000000..8810381
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirCompress.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+import org.apache.freemarker.core.util.StandardCompress;
+
+/**
+ * AST directive node: {@code #compress}.
+ * An instruction that reduces all sequences of whitespace to a single
+ * space or newline. In addition, leading and trailing whitespace is removed.
+ *
+ * @see org.apache.freemarker.core.util.StandardCompress
+ */
+final class ASTDirCompress extends ASTDirective {
+
+ ASTDirCompress(TemplateElements children) {
+ setChildren(children);
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) throws TemplateException, IOException {
+ ASTElement[] childBuffer = getChildBuffer();
+ if (childBuffer != null) {
+ env.visitAndTransform(childBuffer, StandardCompress.INSTANCE, null);
+ }
+ return null;
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ if (canonical) {
+ return "<" + getNodeTypeSymbol() + ">" + getChildrenCanonicalForm() + "</" + getNodeTypeSymbol() + ">";
+ } else {
+ return getNodeTypeSymbol();
+ }
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return "#compress";
+ }
+
+ @Override
+ int getParameterCount() {
+ return 0;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ boolean isIgnorable(boolean stripWhitespace) {
+ return getChildCount() == 0 && getParameterCount() == 0;
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3fd56062/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java
new file mode 100644
index 0000000..7aafd2f
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTDirElseOfList.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+/**
+ * AST directive node: {@code #else} inside a {@code #list}.
+ */
+final class ASTDirElseOfList extends ASTDirective {
+
+ ASTDirElseOfList(TemplateElements children) {
+ setChildren(children);
+ }
+
+ @Override
+ ASTElement[] accept(Environment env) throws TemplateException, IOException {
+ return getChildBuffer();
+ }
+
+ @Override
+ protected String dump(boolean canonical) {
+ if (canonical) {
+ StringBuilder buf = new StringBuilder();
+ buf.append('<').append(getNodeTypeSymbol()).append('>');
+ buf.append(getChildrenCanonicalForm());
+ return buf.toString();
+ } else {
+ return getNodeTypeSymbol();
+ }
+ }
+
+ @Override
+ String getNodeTypeSymbol() {
+ return "#else";
+ }
+
+ @Override
+ int getParameterCount() {
+ return 0;
+ }
+
+ @Override
+ Object getParameterValue(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ ParameterRole getParameterRole(int idx) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ boolean isNestedBlockRepeater() {
+ return false;
+ }
+
+}