/*
 * Copyright 2016-2020 DiffPlug
 *
 * Licensed 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 com.diffplug.spotless;

import java.io.File;
import java.util.Objects;

/**
 * A `Function<String, String>` which can throw an exception.
 * Also the `BiFunction<String, File, String>` is supported, whereas the default
 * implementation only requires the `Function<String, String>` implementation.
 */
public interface FormatterFunc
		extends ThrowingEx.Function<String, String>, ThrowingEx.BiFunction<String, File, String> {

	@Override
	default String apply(String unix, File file) throws Exception {
		return apply(unix);
	}

	/**
	 * `Function<String, String>` and `BiFunction<String, File, String>` whose implementation
	 * requires a resource which should be released when the function is no longer needed.
	 */
	interface Closeable extends FormatterFunc, AutoCloseable {
		@Override
		void close();

		/** Creates a {@link Closeable} from an AutoCloseable and a function. */
		public static Closeable of(AutoCloseable closeable, FormatterFunc function) {
			Objects.requireNonNull(closeable, "closeable");
			Objects.requireNonNull(function, "function");
			return new Closeable() {
				@Override
				public void close() {
					ThrowingEx.run(closeable::close);
				}

				@Override
				public String apply(String unix, File file) throws Exception {
					return function.apply(Objects.requireNonNull(unix), Objects.requireNonNull(file));
				}

				@Override
				public String apply(String unix) throws Exception {
					return function.apply(Objects.requireNonNull(unix));
				}
			};
		}
	}
}

@@ -900,16 +900,37 @@
 on.%0A */%0A
+@FunctionalInterface%0A
 public i
@@ -2117,11 +2117,1067 @@
 ;%0A%09%09%7D%0A%09%7D
+%0A%0A%09/**%0A%09 * Ideally, formatters don't need the underlying file. But in case they do, they should only use it's path,%0A%09 * and should never read the content inside the file, because that breaks the %60Function%3CString, String%3E%60 composition%0A%09 * that Spotless is based on.  For the rare case that you need access to the file, use this method%0A%09 * or %7B@link NeedsFile%7D to create a %7B@link FormatterFunc%7D which needs the File.%0A%09 */%0A%09static FormatterFunc needsFile(NeedsFile needsFile) %7B%0A%09%09return needsFile;%0A%09%7D%0A%0A%09/** @see FormatterFunc#needsFile(NeedsFile) */%0A%09@FunctionalInterface%0A%09interface NeedsFile extends FormatterFunc %7B%0A%09%09String applyWithFile(String unix, File file) throws Exception;%0A%0A%09%09@Override%0A%09%09default String apply(String unix, File file) throws Exception %7B%0A%09%09%09if (file == null) %7B%0A%09%09%09%09throw new IllegalArgumentException(%22This step requires the underlying file. If this is a test, use StepHarnessWithFile%22);%0A%09%09%09%7D%0A%09%09%09return applyWithFile(unix, file);%0A%09%09%7D%0A%0A%09%09@Override%0A%09%09default String apply(String unix) throws Exception %7B%0A%09%09%09return apply(unix, null);%0A%09%09%7D%0A%09%7D
 %0A%7D%0A

Create FormatterFunc.NeedsFile