1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.lint; 18 19 import static com.android.SdkConstants.DOT_XML; 20 21 import com.android.ide.eclipse.adt.AdtPlugin; 22 import com.android.ide.eclipse.adt.AdtUtils; 23 import com.android.ide.eclipse.adt.internal.editors.IconFactory; 24 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 25 import com.android.tools.lint.detector.api.LintUtils; 26 27 import org.eclipse.core.resources.IFile; 28 import org.eclipse.core.resources.IProject; 29 import org.eclipse.core.resources.IResource; 30 import org.eclipse.jdt.core.IJavaProject; 31 import org.eclipse.jdt.ui.JavaElementLabelProvider; 32 import org.eclipse.jface.action.Action; 33 import org.eclipse.jface.action.ActionContributionItem; 34 import org.eclipse.jface.action.IAction; 35 import org.eclipse.jface.action.IMenuCreator; 36 import org.eclipse.jface.action.Separator; 37 import org.eclipse.jface.dialogs.MessageDialog; 38 import org.eclipse.jface.resource.ImageDescriptor; 39 import org.eclipse.jface.viewers.ILabelProvider; 40 import org.eclipse.jface.viewers.ISelection; 41 import org.eclipse.swt.widgets.Control; 42 import org.eclipse.swt.widgets.Menu; 43 import org.eclipse.ui.IObjectActionDelegate; 44 import org.eclipse.ui.ISharedImages; 45 import org.eclipse.ui.IWorkbenchPart; 46 import org.eclipse.ui.IWorkbenchWindow; 47 import org.eclipse.ui.IWorkbenchWindowPulldownDelegate; 48 import org.eclipse.ui.PlatformUI; 49 import org.eclipse.ui.texteditor.ITextEditor; 50 51 import java.util.ArrayList; 52 import java.util.List; 53 54 /** 55 * Action which runs Lint on the currently projects (and also provides a 56 * pulldown menu in the toolbar for selecting specifically which projects to 57 * check) 58 */ 59 public class RunLintAction implements IObjectActionDelegate, IMenuCreator, 60 IWorkbenchWindowPulldownDelegate { 61 62 private ISelection mSelection; 63 private Menu mMenu; 64 65 @Override selectionChanged(IAction action, ISelection selection)66 public void selectionChanged(IAction action, ISelection selection) { 67 mSelection = selection; 68 } 69 70 @Override run(IAction action)71 public void run(IAction action) { 72 List<IProject> projects = getProjects(mSelection, true /* warn */); 73 74 if (!projects.isEmpty()) { 75 EclipseLintRunner.startLint(projects, null, null, false /*fatalOnly*/, true /*show*/); 76 } 77 } 78 79 /** Returns the Android project(s) to apply a lint run to. */ getProjects(ISelection selection, boolean warn)80 static List<IProject> getProjects(ISelection selection, boolean warn) { 81 List<IProject> projects = AdtUtils.getSelectedProjects(selection); 82 83 if (projects.isEmpty() && warn) { 84 MessageDialog.openWarning(AdtPlugin.getShell(), "Lint", 85 "Could not run Lint: Select an Android project first."); 86 } 87 88 return projects; 89 } 90 91 @Override setActivePart(IAction action, IWorkbenchPart targetPart)92 public void setActivePart(IAction action, IWorkbenchPart targetPart) { 93 } 94 95 @Override dispose()96 public void dispose() { 97 if (mMenu != null) { 98 mMenu.dispose(); 99 } 100 } 101 102 @Override init(IWorkbenchWindow window)103 public void init(IWorkbenchWindow window) { 104 } 105 106 // ---- IMenuCreator ---- 107 108 @Override getMenu(Control parent)109 public Menu getMenu(Control parent) { 110 mMenu = new Menu(parent); 111 112 IconFactory iconFactory = IconFactory.getInstance(); 113 ImageDescriptor allIcon = iconFactory.getImageDescriptor("lintrun"); //$NON-NLS-1$ 114 LintMenuAction allAction = new LintMenuAction("Check All Projects", allIcon, 115 ACTION_RUN, null); 116 117 addAction(allAction); 118 addSeparator(); 119 IJavaProject[] projects = AdtUtils.getOpenAndroidProjects(); 120 ILabelProvider provider = new JavaElementLabelProvider( 121 JavaElementLabelProvider.SHOW_DEFAULT); 122 for (IJavaProject project : projects) { 123 IProject p = project.getProject(); 124 ImageDescriptor icon = ImageDescriptor.createFromImage(provider.getImage(p)); 125 String label = String.format("Check %1$s", p.getName()); 126 LintMenuAction projectAction = new LintMenuAction(label, icon, ACTION_RUN, p); 127 addAction(projectAction); 128 } 129 130 ITextEditor textEditor = AdtUtils.getActiveTextEditor(); 131 if (textEditor != null) { 132 IFile file = AdtUtils.getActiveFile(); 133 // Currently only supported for XML files 134 if (file != null && LintUtils.endsWith(file.getName(), DOT_XML)) { 135 ImageDescriptor icon = ImageDescriptor.createFromImage(provider.getImage(file)); 136 IAction fileAction = new LintMenuAction("Check Current File", icon, ACTION_RUN, 137 file); 138 139 addSeparator(); 140 addAction(fileAction); 141 } 142 } 143 144 ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); 145 ImageDescriptor clear = images.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVEALL); 146 LintMenuAction clearAction = new LintMenuAction("Clear Lint Warnings", clear, ACTION_CLEAR, 147 null); 148 addSeparator(); 149 addAction(clearAction); 150 151 LintMenuAction excludeAction = new LintMenuAction("Skip Library Project Dependencies", 152 allIcon, ACTION_TOGGLE_EXCLUDE, null); 153 addSeparator(); 154 addAction(excludeAction); 155 excludeAction.setChecked(AdtPrefs.getPrefs().getSkipLibrariesFromLint()); 156 157 return mMenu; 158 } 159 addAction(IAction action)160 private void addAction(IAction action) { 161 ActionContributionItem item = new ActionContributionItem(action); 162 item.fill(mMenu, -1); 163 } 164 addSeparator()165 private void addSeparator() { 166 new Separator().fill(mMenu, -1); 167 } 168 169 @Override getMenu(Menu parent)170 public Menu getMenu(Menu parent) { 171 return null; 172 } 173 174 private static final int ACTION_RUN = 1; 175 private static final int ACTION_CLEAR = 2; 176 private static final int ACTION_TOGGLE_EXCLUDE = 3; 177 178 /** 179 * Actions in the pulldown context menu: run lint or clear lint markers on 180 * the given resource 181 */ 182 private static class LintMenuAction extends Action { 183 private final IResource mResource; 184 private final int mAction; 185 186 /** 187 * Creates a new context menu action 188 * 189 * @param text the label 190 * @param descriptor the icon 191 * @param action the action to run: run lint, clear, or toggle exclude libraries 192 * @param resource the resource to check or clear markers for, where 193 * null means all projects 194 */ LintMenuAction(String text, ImageDescriptor descriptor, int action, IResource resource)195 private LintMenuAction(String text, ImageDescriptor descriptor, int action, 196 IResource resource) { 197 super(text, action == ACTION_TOGGLE_EXCLUDE ? AS_CHECK_BOX : AS_PUSH_BUTTON); 198 if (descriptor != null) { 199 setImageDescriptor(descriptor); 200 } 201 mAction = action; 202 mResource = resource; 203 } 204 205 @Override run()206 public void run() { 207 if (mAction == ACTION_TOGGLE_EXCLUDE) { 208 AdtPrefs prefs = AdtPrefs.getPrefs(); 209 prefs.setSkipLibrariesFromLint(!prefs.getSkipLibrariesFromLint()); 210 return; 211 } 212 List<IResource> resources = new ArrayList<IResource>(); 213 if (mResource == null) { 214 // All projects 215 IJavaProject[] open = AdtUtils.getOpenAndroidProjects(); 216 for (IJavaProject project : open) { 217 resources.add(project.getProject()); 218 } 219 } else { 220 resources.add(mResource); 221 } 222 EclipseLintRunner.cancelCurrentJobs(false); 223 if (mAction == ACTION_CLEAR) { 224 EclipseLintClient.clearMarkers(resources); 225 } else { 226 assert mAction == ACTION_RUN; 227 EclipseLintRunner.startLint(resources, null, null, false /*fatalOnly*/, 228 true /*show*/); 229 } 230 } 231 } 232 } 233