All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gradle.internal.deprecation.DeprecationLogger Maven / Gradle / Ivy

/*
 * Copyright 2020 the original author or authors.
 *
 * 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 org.gradle.internal.deprecation;

import org.gradle.api.logging.configuration.WarningMode;
import org.gradle.internal.Factory;
import org.gradle.internal.featurelifecycle.LoggingDeprecatedFeatureHandler;
import org.gradle.internal.featurelifecycle.UsageLocationReporter;
import org.gradle.internal.operations.BuildOperationProgressEventEmitter;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;


/**
 * Provides entry points for constructing and emitting deprecation messages.
 * The basic deprecation message structure is "Summary. DeprecationTimeline. Context. Advice. Documentation."
 *
 * The deprecateX methods in this class return a builder that guides creation of the deprecation message.
 * Summary is populated by the deprecateX methods in this class.
 * Context can be added in free text using {@link DeprecationMessageBuilder#withContext(String)}.
 * Advice is constructed contextually using {@link DeprecationMessageBuilder.WithReplacement#replaceWith(Object)} methods based on the thing being deprecated. Alternatively, it can be populated using {@link DeprecationMessageBuilder#withAdvice(String)}.
 * DeprecationTimeline is mandatory and is added using one of:
 * - ${@link DeprecationMessageBuilder#willBeRemovedInGradle8()}
 * - ${@link DeprecationMessageBuilder#willBecomeAnErrorInGradle8()}
 * After DeprecationTimeline is set, Documentation reference must be added using one of:
 * - {@link DeprecationMessageBuilder.WithDeprecationTimeline#withUpgradeGuideSection(int, String)}
 * - {@link DeprecationMessageBuilder.WithDeprecationTimeline#withDslReference(Class, String)}
 * - {@link DeprecationMessageBuilder.WithDeprecationTimeline#withUserManual(String, String)}
 *
 * In order for the deprecation message to be emitted, terminal operation {@link DeprecationMessageBuilder.WithDocumentation#nagUser()} has to be called after one of the documentation providing methods.
 */
@ThreadSafe
public class DeprecationLogger {

    private static final ThreadLocal ENABLED = new ThreadLocal() {
        @Override
        protected Boolean initialValue() {
            return true;
        }
    };

    private static final LoggingDeprecatedFeatureHandler DEPRECATED_FEATURE_HANDLER = new LoggingDeprecatedFeatureHandler();

    public synchronized static void init(UsageLocationReporter reporter, WarningMode warningMode, BuildOperationProgressEventEmitter buildOperationProgressEventEmitter) {
        DEPRECATED_FEATURE_HANDLER.init(reporter, warningMode, buildOperationProgressEventEmitter);
    }

    public synchronized static void reset() {
        DEPRECATED_FEATURE_HANDLER.reset();
    }

    public synchronized static void reportSuppressedDeprecations() {
        DEPRECATED_FEATURE_HANDLER.reportSuppressedDeprecations();
    }

    @Nullable
    public static Throwable getDeprecationFailure() {
        return DEPRECATED_FEATURE_HANDLER.getDeprecationFailure();
    }

    /**
     * This is a rather generic deprecation entry point - consider using a more specific deprecation method and only resort to this one if there is no fit.
     *
     * Output: ${feature} has been deprecated.
     */
    @CheckReturnValue
    @SuppressWarnings("rawtypes")
    public static DeprecationMessageBuilder deprecate(final String feature) {
        return new DeprecationMessageBuilder() {
            @Override
            DeprecationMessage build() {
                setSummary(xHasBeenDeprecated(feature));
                return super.build();
            }
        };
    }

    /**
     * Indirect usage means that stack trace at the time the deprecation is logged does not indicate the call site.
     * This directs GE to not display unhelpful stacktraces with the deprecation.
     *
     * Output: ${feature} has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder deprecateIndirectUsage(String feature) {
        DeprecationMessageBuilder builder = deprecate(feature);
        builder.setIndirectUsage();
        return builder;
    }

    /**
     * Output: ${feature} has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder deprecateBuildInvocationFeature(String feature) {
        DeprecationMessageBuilder builder = deprecate(feature);
        builder.setBuildInvocationUsage();
        return builder;
    }

    /**
     * Output: ${behaviour}.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateBehaviour deprecateBehaviour(String behaviour) {
        return new DeprecationMessageBuilder.DeprecateBehaviour(behaviour);
    }

    /**
     * Output: ${behaviour} ${advice}
     */
    @CheckReturnValue
    @SuppressWarnings("rawtypes")
    public static DeprecationMessageBuilder.WithDeprecationTimeline warnOfChangedBehaviour(final String behaviour, final String advice) {
        return new DeprecationMessageBuilder.WithDeprecationTimeline(new DeprecationMessageBuilder() {
            @Override
            DeprecationMessage build() {
                return new DeprecationMessage(behaviour, "", advice, null, Documentation.NO_DOCUMENTATION, DeprecatedFeatureUsage.Type.USER_CODE_INDIRECT);
            }
        });
    }

    /**
     * Output: ${action} has been deprecated.
     */
    @CheckReturnValue
    @SuppressWarnings("rawtypes")
    public static DeprecationMessageBuilder deprecateAction(final String action) {
        return new DeprecationMessageBuilder() {
            @Override
            DeprecationMessage build() {
                setSummary(xHasBeenDeprecated(action));
                return super.build();
            }
        };
    }

    /**
     * Output: The ${property} property has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateProperty deprecateProperty(Class propertyClass, String property) {
        return new DeprecationMessageBuilder.DeprecateProperty(propertyClass, property);
    }

    /**
     * Output: The ${property} system property has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateSystemProperty deprecateSystemProperty(String systemProperty) {
        return new DeprecationMessageBuilder.DeprecateSystemProperty(systemProperty);
    }

    /**
     * Output: The ${parameter} named parameter has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateNamedParameter deprecateNamedParameter(String parameter) {
        return new DeprecationMessageBuilder.DeprecateNamedParameter(parameter);
    }

    /**
     * Output: The ${method} method has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateMethod deprecateMethod(Class methodClass, String methodWithParams) {
        return new DeprecationMessageBuilder.DeprecateMethod(methodClass, methodWithParams);
    }

    /**
     * Output: Using method ${invocation} has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateInvocation deprecateInvocation(String methodWithParams) {
        return new DeprecationMessageBuilder.DeprecateInvocation(methodWithParams);
    }

    /**
     * Output: The ${task} task has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateTask deprecateTask(String task) {
        return new DeprecationMessageBuilder.DeprecateTask(task);
    }

    /**
     * Output: The task type ${task.getCanonicalName()} (used by the ${task.getPath()} task) has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateTaskType deprecateTaskType(Class task, String path) {
        return new DeprecationMessageBuilder.DeprecateTaskType(task.getCanonicalName(), path);
    }

    /**
     * Output: The ${plugin} plugin has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecatePlugin deprecatePlugin(String plugin) {
        return new DeprecationMessageBuilder.DeprecatePlugin(plugin);
    }

    /**
     * Output: Internal API ${api} has been deprecated.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.DeprecateInternalApi deprecateInternalApi(String api) {
        return new DeprecationMessageBuilder.DeprecateInternalApi(api);
    }

    /**
     * Output: The ${configurationType} configuration has been deprecated for ${declarationType}.
     */
    @CheckReturnValue
    public static DeprecationMessageBuilder.ConfigurationDeprecationTypeSelector deprecateConfiguration(String configurationType) {
        return new DeprecationMessageBuilder.ConfigurationDeprecationTypeSelector(configurationType);
    }

    static void nagUserWith(DeprecationMessageBuilder deprecationMessageBuilder, Class calledFrom) {
        if (isEnabled()) {
            DeprecationMessage deprecationMessage = deprecationMessageBuilder.build();
            nagUserWith(deprecationMessage.toDeprecatedFeatureUsage(calledFrom));
        }
    }

    @Nullable
    public static  T whileDisabled(Factory factory) {
        ENABLED.set(false);
        try {
            return factory.create();
        } finally {
            ENABLED.set(true);
        }
    }

    public static void whileDisabled(Runnable action) {
        ENABLED.set(false);
        try {
            action.run();
        } finally {
            ENABLED.set(true);
        }
    }

    private static boolean isEnabled() {
        return ENABLED.get();
    }

    private synchronized static void nagUserWith(DeprecatedFeatureUsage usage) {
        DEPRECATED_FEATURE_HANDLER.featureUsed(usage);
    }

    private static String xHasBeenDeprecated(String x) {
        return String.format("%s has been deprecated.", x);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy