com.android.tools.idea.gradle.service.notification.errors.GradleDslMethodNotFoundErrorHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.android.tools.idea.gradle.service.notification.errors.GradleDslMethodNotFoundErrorHandler.java

Source

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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.android.tools.idea.gradle.service.notification.errors;

import com.android.tools.idea.gradle.service.notification.hyperlink.NotificationHyperlink;
import com.android.tools.idea.gradle.service.notification.hyperlink.OpenGradleSettingsHyperlink;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.externalSystem.service.notification.NotificationCategory;
import com.intellij.openapi.externalSystem.service.notification.NotificationData;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.playback.commands.ActionCommand;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.codeInsight.actions.AddGradleDslPluginAction;
import org.jetbrains.plugins.gradle.settings.DistributionType;
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;

import java.io.File;
import java.util.List;

import static com.android.SdkConstants.FN_BUILD_GRADLE;
import static com.android.tools.idea.gradle.project.ProjectImportErrorHandler.GRADLE_DSL_METHOD_NOT_FOUND_ERROR_PREFIX;
import static com.android.tools.idea.gradle.util.GradleUtil.findWrapperPropertiesFile;
import static com.android.tools.idea.gradle.util.GradleUtil.getGradleProjectSettings;
import static com.intellij.openapi.vfs.VfsUtil.findFileByIoFile;

public class GradleDslMethodNotFoundErrorHandler extends AbstractSyncErrorHandler {
    @Override
    public boolean handleError(@NotNull List<String> message, @NotNull ExternalSystemException error,
            @NotNull NotificationData notification, @NotNull Project project) {
        String firstLine = message.get(0);

        if (firstLine != null && firstLine.startsWith(GRADLE_DSL_METHOD_NOT_FOUND_ERROR_PREFIX)) {
            String filePath = notification.getFilePath();
            final VirtualFile virtualFile = filePath != null
                    ? LocalFileSystem.getInstance().refreshAndFindFileByPath(filePath)
                    : null;
            if (virtualFile != null && FN_BUILD_GRADLE.equals(virtualFile.getName())) {
                NotificationHyperlink gradleSettingsHyperlink = getGradleSettingsHyperlink(project);
                NotificationHyperlink applyGradlePluginHyperlink = getApplyGradlePluginHyperlink(virtualFile,
                        notification);

                String newMsg = firstLine + "\nPossible causes:<ul>" + String.format(
                        "<li>The project '%1$s' may be using a version of Gradle that does not contain the method.\n",
                        project.getName()) + gradleSettingsHyperlink.toHtml() + "</li>"
                        + "<li>The build file may be missing a Gradle plugin.\n"
                        + applyGradlePluginHyperlink.toHtml() + "</li>";
                String title = String.format(FAILED_TO_SYNC_GRADLE_PROJECT_ERROR_GROUP_FORMAT, project.getName());
                notification.setTitle(title);
                notification.setMessage(newMsg);
                notification.setNotificationCategory(NotificationCategory.convert(DEFAULT_NOTIFICATION_TYPE));

                addNotificationListener(notification, project, gradleSettingsHyperlink, applyGradlePluginHyperlink);
            } else if (virtualFile != null && notification.getLine() > 0 && notification.getNavigatable() == null) {
                OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile,
                        notification.getLine() - 1 /* lines are zero-based */, -1);
                notification.setNavigatable(descriptor);
            } else {
                updateNotification(notification, project, error.getMessage());
            }
            return true;
        }
        return false;
    }

    @NotNull
    private static NotificationHyperlink getGradleSettingsHyperlink(@NotNull Project project) {
        if (isUsingWrapper(project)) {
            File wrapperPropertiesFile = findWrapperPropertiesFile(project);
            if (wrapperPropertiesFile != null) {
                final VirtualFile virtualFile = findFileByIoFile(wrapperPropertiesFile, true);
                if (virtualFile != null) {
                    return new NotificationHyperlink("open.wrapper.file", "Open Gradle wrapper file") {
                        @Override
                        protected void execute(@NotNull Project project) {
                            OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile);
                            FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
                        }
                    };
                }
            }
        }
        return new OpenGradleSettingsHyperlink();
    }

    private static boolean isUsingWrapper(@NotNull Project project) {
        GradleProjectSettings gradleSettings = getGradleProjectSettings(project);
        File wrapperPropertiesFile = findWrapperPropertiesFile(project);

        DistributionType distributionType = gradleSettings != null ? gradleSettings.getDistributionType() : null;

        return (distributionType == null || distributionType == DistributionType.DEFAULT_WRAPPED)
                && wrapperPropertiesFile != null;
    }

    @NotNull
    private static NotificationHyperlink getApplyGradlePluginHyperlink(@NotNull final VirtualFile virtualFile,
            @NotNull final NotificationData notification) {
        return new NotificationHyperlink("apply.gradle.plugin", "Apply Gradle plugin") {
            @Override
            protected void execute(@NotNull Project project) {
                openFile(virtualFile, notification, project);

                ActionManager actionManager = ActionManager.getInstance();
                String actionId = AddGradleDslPluginAction.ID;
                AnAction action = actionManager.getAction(actionId);
                assert action instanceof AddGradleDslPluginAction;
                AddGradleDslPluginAction addPluginAction = (AddGradleDslPluginAction) action;
                actionManager.tryToExecute(addPluginAction, ActionCommand.getInputEvent(actionId), null,
                        ActionPlaces.UNKNOWN, true);
            }
        };
    }

    private static void openFile(@NotNull VirtualFile virtualFile, @NotNull NotificationData notification,
            @NotNull Project project) {
        int line = notification.getLine() - 1;
        int column = notification.getColumn() - 1;

        line = line < 0 ? -1 : line; // NotificationData uses 1-based offsets, while OpenFileDescriptor 0-based.
        column = column < 0 ? -1 : column + 1;
        new OpenFileDescriptor(project, virtualFile, line, column).navigate(true);
    }
}