/******************************************************************************* * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * *******************************************************************************/ package com.liferay.ide.gradle.ui.quickfix; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.imageio.ImageIO; import org.eclipse.buildship.core.CorePlugin; import org.eclipse.buildship.core.workspace.NewProjectHandler; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.ui.text.java.IInvocationContext; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; import org.eclipse.jdt.ui.text.java.IProblemLocation; import org.eclipse.jdt.ui.text.java.IQuickFixProcessor; import org.eclipse.jdt.ui.text.java.correction.CUCorrectionProposal; import org.eclipse.jface.text.IDocument; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import com.liferay.ide.gradle.core.GradleCore; import com.liferay.ide.gradle.core.parser.GradleDependency; import com.liferay.ide.gradle.core.parser.GradleDependencyUpdater; import com.liferay.ide.gradle.ui.GradleUI; import com.liferay.ide.project.core.ProjectCore; import com.liferay.ide.project.core.modules.ServiceContainer; import com.liferay.ide.project.core.util.TargetPlatformUtil; import com.liferay.ide.project.ui.ProjectUI; import com.liferay.ide.ui.util.UIUtil; /** * @author Lovett Li */ public class QuickFixGradleDep implements IQuickFixProcessor { private IFile gradleFile; @Override public boolean hasCorrections( ICompilationUnit unit, int problemId ) { switch( problemId ) { case IProblem.ImportNotFound: case IProblem.UndefinedType: return true; default: return false; } } @Override public IJavaCompletionProposal[] getCorrections( IInvocationContext context, IProblemLocation[] locations ) { if( locations == null || locations.length == 0 ) { return null; } IProject project = context.getCompilationUnit().getResource().getProject(); gradleFile = project.getFile( "build.gradle" ); List<IJavaCompletionProposal> resultingCollections = new ArrayList<>(); if( gradleFile.exists() ) { for( int i = 0; i < locations.length; i++ ) { IProblemLocation curr = locations[i]; process( context, curr, resultingCollections ); } } return resultingCollections.toArray( new IJavaCompletionProposal[resultingCollections.size()] ); } private void process( IInvocationContext context, IProblemLocation problem, List<IJavaCompletionProposal> proposals ) { int id = problem.getProblemId(); if( id == 0 ) { return; } switch( id ) { case IProblem.ImportNotFound: importNotFoundProposal( context, problem, proposals ); break; case IProblem.UndefinedType: undefinedType( context, problem, proposals ); break; default:; } } private void undefinedType( IInvocationContext context, IProblemLocation problem, Collection<IJavaCompletionProposal> proposals ) { ASTNode selectedNode = problem.getCoveringNode( context.getASTRoot() ); String fullyQualifiedName = null; if( selectedNode instanceof Name ) { Name node = (Name) selectedNode; fullyQualifiedName = node.getFullyQualifiedName(); } List<String> serviceWrapperList; List<String> servicesList; boolean depWrapperCanFixed = false; try { serviceWrapperList = TargetPlatformUtil.getServiceWrapperList().getServiceList(); servicesList = TargetPlatformUtil.getServicesList().getServiceList(); for( String wrapper : serviceWrapperList ) { if( wrapper.endsWith( fullyQualifiedName ) ) { ServiceContainer bundle = TargetPlatformUtil.getServiceWrapperBundle( wrapper ); createDepProposal( context, proposals, bundle ); } } if( !depWrapperCanFixed ) { for( String service : servicesList ) { if( service.endsWith( fullyQualifiedName ) ) { ServiceContainer bundle = TargetPlatformUtil.getServiceBundle( service ); createDepProposal( context, proposals, bundle ); } } } } catch( Exception e ) { GradleCore.logError( "Gradle dependence got error", e ); } } private void importNotFoundProposal( IInvocationContext context, IProblemLocation problem, Collection<IJavaCompletionProposal> proposals ) { ASTNode selectedNode = problem.getCoveringNode( context.getASTRoot() ); if( selectedNode == null ) { return; } ImportDeclaration importDeclaration = (ImportDeclaration) ASTNodes.getParent( selectedNode, ASTNode.IMPORT_DECLARATION ); if( importDeclaration == null ) { return; } String importName = importDeclaration.getName().toString(); List<String> serviceWrapperList; List<String> servicesList; boolean depWrapperCanFixed = false; try { serviceWrapperList = TargetPlatformUtil.getServiceWrapperList().getServiceList(); servicesList = TargetPlatformUtil.getServicesList().getServiceList(); if( serviceWrapperList.contains( importName ) ) { ServiceContainer bundle = TargetPlatformUtil.getServiceWrapperBundle( importName ); depWrapperCanFixed = true; createDepProposal( context, proposals, bundle ); } if( !depWrapperCanFixed ) { if( servicesList.contains( importName ) ) { ServiceContainer bundle = TargetPlatformUtil.getServiceBundle( importName ); createDepProposal( context, proposals, bundle ); } } if( TargetPlatformUtil.getThirdPartyBundleList( importName ) != null ) { ServiceContainer bundle = TargetPlatformUtil.getThirdPartyBundleList( importName ); createDepProposal( context, proposals, bundle ); } } catch( Exception e ) { GradleCore.logError( "Gradle dependence got error", e ); } } private void createDepProposal( IInvocationContext context, Collection<IJavaCompletionProposal> proposals, ServiceContainer bundle ) { final String bundleGroup = bundle.getBundleGroup(); final String bundleName = bundle.getBundleName(); final String bundleVersion = bundle.getBundleVersion(); proposals.add( new CUCorrectionProposal( "Add Gradle Dependence " + bundleName, context.getCompilationUnit(), null, -0 ) { @Override public void apply( IDocument document ) { try { GradleDependencyUpdater updater = new GradleDependencyUpdater( gradleFile.getLocation().toFile() ); List<GradleDependency> existDependencies = updater.getAllDependencies(); GradleDependency gd = new GradleDependency( bundleGroup, bundleName, bundleVersion ); if( !existDependencies.contains( gd ) ) { updater.insertDependency( gd ); Files.write( gradleFile.getLocation().toFile().toPath(), updater.getGradleFileContents(), StandardCharsets.UTF_8 ); IProject project = context.getCompilationUnit().getResource().getProject(); Set<IProject> set = new HashSet<>(); set.add( project ); CorePlugin.gradleWorkspaceManager().getCompositeBuild( set ).synchronize( NewProjectHandler.IMPORT_AND_MERGE ); } } catch( Exception e ) { GradleCore.logError( "Gradle dependence got error", e ); } } @Override public Object getAdditionalProposalInfo( IProgressMonitor monitor ) { return "Add dependenece"; } @Override public Image getImage() { Display display = UIUtil.getActiveShell().getDisplay(); String file = null; try { file = FileLocator.toFileURL( GradleUI.getDefault().getBundle().getEntry( "icons/e16/liferay_logo_16.png" ) ).getFile(); } catch( IOException e ) { GradleUI.logError( e ); } return new Image( display, file ); } } ); } }