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 package com.android.ide.eclipse.adt.internal.lint; 17 18 import static com.android.SdkConstants.DOT_JAVA; 19 import static com.android.SdkConstants.DOT_XML; 20 21 import com.android.ide.eclipse.adt.AdtPlugin; 22 import com.android.ide.eclipse.adt.internal.editors.IconFactory; 23 import com.android.ide.eclipse.adt.internal.preferences.LintPreferencePage; 24 import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; 25 import com.android.tools.lint.detector.api.LintUtils; 26 27 import org.eclipse.core.resources.IFile; 28 import org.eclipse.core.resources.IFolder; 29 import org.eclipse.core.resources.IMarker; 30 import org.eclipse.core.resources.IProject; 31 import org.eclipse.core.resources.IResource; 32 import org.eclipse.core.runtime.CoreException; 33 import org.eclipse.core.runtime.NullProgressMonitor; 34 import org.eclipse.core.runtime.jobs.IJobChangeEvent; 35 import org.eclipse.core.runtime.jobs.IJobChangeListener; 36 import org.eclipse.core.runtime.jobs.Job; 37 import org.eclipse.jdt.core.IJavaProject; 38 import org.eclipse.jface.action.Action; 39 import org.eclipse.jface.action.IStatusLineManager; 40 import org.eclipse.jface.action.IToolBarManager; 41 import org.eclipse.jface.action.Separator; 42 import org.eclipse.jface.preference.IPreferenceNode; 43 import org.eclipse.jface.preference.PreferenceDialog; 44 import org.eclipse.jface.preference.PreferenceManager; 45 import org.eclipse.jface.preference.PreferenceNode; 46 import org.eclipse.jface.resource.ImageDescriptor; 47 import org.eclipse.jface.text.IDocument; 48 import org.eclipse.jface.text.IRegion; 49 import org.eclipse.jface.text.Region; 50 import org.eclipse.swt.SWT; 51 import org.eclipse.swt.custom.SashForm; 52 import org.eclipse.swt.events.SelectionEvent; 53 import org.eclipse.swt.events.SelectionListener; 54 import org.eclipse.swt.layout.GridData; 55 import org.eclipse.swt.layout.GridLayout; 56 import org.eclipse.swt.widgets.Composite; 57 import org.eclipse.swt.widgets.Display; 58 import org.eclipse.swt.widgets.Label; 59 import org.eclipse.swt.widgets.Shell; 60 import org.eclipse.swt.widgets.Text; 61 import org.eclipse.ui.IMemento; 62 import org.eclipse.ui.ISharedImages; 63 import org.eclipse.ui.IViewPart; 64 import org.eclipse.ui.IViewSite; 65 import org.eclipse.ui.IWorkbench; 66 import org.eclipse.ui.IWorkbenchPage; 67 import org.eclipse.ui.IWorkbenchWindow; 68 import org.eclipse.ui.PartInitException; 69 import org.eclipse.ui.PlatformUI; 70 import org.eclipse.ui.editors.text.TextFileDocumentProvider; 71 import org.eclipse.ui.part.ViewPart; 72 import org.eclipse.ui.texteditor.IDocumentProvider; 73 74 import java.util.ArrayList; 75 import java.util.Collections; 76 import java.util.HashSet; 77 import java.util.List; 78 import java.util.Set; 79 80 /** 81 * Eclipse View which shows lint warnings for the current project 82 */ 83 public class LintViewPart extends ViewPart implements SelectionListener, IJobChangeListener { 84 /** The view id for this view part */ 85 public static final String ID = "com.android.ide.eclipse.adt.internal.lint.LintViewPart"; //$NON-NLS-1$ 86 private static final String QUICKFIX_DISABLED_ICON = "quickfix-disabled"; //$NON-NLS-1$ 87 private static final String QUICKFIX_ICON = "quickfix"; //$NON-NLS-1$ 88 private static final String REFRESH_ICON = "refresh"; //$NON-NLS-1$ 89 private static final String EXPAND_DISABLED_ICON = "expandall-disabled"; //$NON-NLS-1$ 90 private static final String EXPAND_ICON = "expandall"; //$NON-NLS-1$ 91 private static final String COLUMNS_ICON = "columns"; //$NON-NLS-1$ 92 private static final String OPTIONS_ICON = "options"; //$NON-NLS-1$ 93 private static final String IGNORE_THIS_ICON = "ignore-this"; //$NON-NLS-1$ 94 private static final String IGNORE_THIS_DISABLED_ICON = "ignore-this-disabled"; //$NON-NLS-1$ 95 private static final String IGNORE_FILE_ICON = "ignore-file"; //$NON-NLS-1$ 96 private static final String IGNORE_FILE_DISABLED_ICON = "ignore-file-disabled"; //$NON-NLS-1$ 97 private static final String IGNORE_PRJ_ICON = "ignore-project"; //$NON-NLS-1$ 98 private static final String IGNORE_PRJ_DISABLED_ICON = "ignore-project-disabled"; //$NON-NLS-1$ 99 private static final String IGNORE_ALL_ICON = "ignore-all"; //$NON-NLS-1$ 100 private static final String IGNORE_ALL_DISABLED_ICON = "ignore-all-disabled"; //$NON-NLS-1$ 101 private IMemento mMemento; 102 private LintList mLintView; 103 private Text mDetailsText; 104 private Label mErrorLabel; 105 private SashForm mSashForm; 106 private Action mFixAction; 107 private Action mRemoveAction; 108 private Action mIgnoreAction; 109 private Action mAlwaysIgnoreAction; 110 private Action mIgnoreFileAction; 111 private Action mIgnoreProjectAction; 112 private Action mRemoveAllAction; 113 private Action mRefreshAction; 114 private Action mExpandAll; 115 private Action mCollapseAll; 116 private Action mConfigureColumns; 117 private Action mOptions; 118 119 /** 120 * Initial projects to show: this field is only briefly not null during the 121 * construction initiated by {@link #show(List)} 122 */ 123 private static List<? extends IResource> sInitialResources; 124 125 /** 126 * Constructs a new {@link LintViewPart} 127 */ LintViewPart()128 public LintViewPart() { 129 } 130 131 @Override init(IViewSite site, IMemento memento)132 public void init(IViewSite site, IMemento memento) throws PartInitException { 133 super.init(site, memento); 134 mMemento = memento; 135 } 136 137 @Override saveState(IMemento memento)138 public void saveState(IMemento memento) { 139 super.saveState(memento); 140 141 mLintView.saveState(memento); 142 } 143 144 @Override dispose()145 public void dispose() { 146 if (mLintView != null) { 147 mLintView.dispose(); 148 mLintView = null; 149 } 150 super.dispose(); 151 } 152 153 @Override createPartControl(Composite parent)154 public void createPartControl(Composite parent) { 155 GridLayout gridLayout = new GridLayout(1, false); 156 gridLayout.verticalSpacing = 0; 157 gridLayout.marginWidth = 0; 158 gridLayout.marginHeight = 0; 159 parent.setLayout(gridLayout); 160 161 mErrorLabel = new Label(parent, SWT.NONE); 162 mErrorLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); 163 164 mSashForm = new SashForm(parent, SWT.NONE); 165 mSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); 166 mLintView = new LintList(getSite(), mSashForm, mMemento, false /*singleFile*/); 167 168 mDetailsText = new Text(mSashForm, 169 SWT.BORDER | SWT.READ_ONLY | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI); 170 Display display = parent.getDisplay(); 171 mDetailsText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); 172 mDetailsText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); 173 174 mLintView.addSelectionListener(this); 175 mSashForm.setWeights(new int[] {8, 2}); 176 177 createActions(); 178 initializeToolBar(); 179 180 // If there are currently running jobs, listen for them such that we can update the 181 // button state 182 refreshStopIcon(); 183 184 if (sInitialResources != null) { 185 mLintView.setResources(sInitialResources); 186 sInitialResources = null; 187 } else { 188 // No supplied context: show lint warnings for all projects 189 IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(null); 190 if (androidProjects.length > 0) { 191 List<IResource> projects = new ArrayList<IResource>(); 192 for (IJavaProject project : androidProjects) { 193 projects.add(project.getProject()); 194 } 195 mLintView.setResources(projects); 196 } 197 } 198 199 updateIssueCount(); 200 } 201 202 /** 203 * Create the actions. 204 */ createActions()205 private void createActions() { 206 ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); 207 IconFactory iconFactory = IconFactory.getInstance(); 208 mFixAction = new LintViewAction("Fix", ACTION_FIX, 209 iconFactory.getImageDescriptor(QUICKFIX_ICON), 210 iconFactory.getImageDescriptor(QUICKFIX_DISABLED_ICON)); 211 212 mIgnoreAction = new LintViewAction("Suppress this error with an annotation/attribute", 213 ACTION_IGNORE_THIS, 214 iconFactory.getImageDescriptor(IGNORE_THIS_ICON), 215 iconFactory.getImageDescriptor(IGNORE_THIS_DISABLED_ICON)); 216 mIgnoreFileAction = new LintViewAction("Ignore in this file", ACTION_IGNORE_FILE, 217 iconFactory.getImageDescriptor(IGNORE_FILE_ICON), 218 iconFactory.getImageDescriptor(IGNORE_FILE_DISABLED_ICON)); 219 mIgnoreProjectAction = new LintViewAction("Ignore in this project", ACTION_IGNORE_TYPE, 220 iconFactory.getImageDescriptor(IGNORE_PRJ_ICON), 221 iconFactory.getImageDescriptor(IGNORE_PRJ_DISABLED_ICON)); 222 mAlwaysIgnoreAction = new LintViewAction("Always Ignore", ACTION_IGNORE_ALL, 223 iconFactory.getImageDescriptor(IGNORE_ALL_ICON), 224 iconFactory.getImageDescriptor(IGNORE_ALL_DISABLED_ICON)); 225 226 mRemoveAction = new LintViewAction("Remove", ACTION_REMOVE, 227 sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVE), 228 sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVE_DISABLED)); 229 mRemoveAllAction = new LintViewAction("Remove All", ACTION_REMOVE_ALL, 230 sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVEALL), 231 sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVEALL_DISABLED)); 232 mRefreshAction = new LintViewAction("Refresh (& Save Files)", ACTION_REFRESH, 233 iconFactory.getImageDescriptor(REFRESH_ICON), null); 234 mRemoveAllAction.setEnabled(true); 235 mCollapseAll = new LintViewAction("Collapse All", ACTION_COLLAPSE, 236 sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL), 237 sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL_DISABLED)); 238 mCollapseAll.setEnabled(true); 239 mExpandAll = new LintViewAction("Expand All", ACTION_EXPAND, 240 iconFactory.getImageDescriptor(EXPAND_ICON), 241 iconFactory.getImageDescriptor(EXPAND_DISABLED_ICON)); 242 mExpandAll.setEnabled(true); 243 244 mConfigureColumns = new LintViewAction("Configure Columns...", ACTION_COLUMNS, 245 iconFactory.getImageDescriptor(COLUMNS_ICON), 246 null); 247 248 mOptions = new LintViewAction("Options...", ACTION_OPTIONS, 249 iconFactory.getImageDescriptor(OPTIONS_ICON), 250 null); 251 252 enableActions(Collections.<IMarker>emptyList(), false /*updateWidgets*/); 253 } 254 255 /** 256 * Initialize the toolbar. 257 */ initializeToolBar()258 private void initializeToolBar() { 259 IToolBarManager toolbarManager = getViewSite().getActionBars().getToolBarManager(); 260 toolbarManager.add(mRefreshAction); 261 toolbarManager.add(mFixAction); 262 toolbarManager.add(mIgnoreAction); 263 toolbarManager.add(mIgnoreFileAction); 264 toolbarManager.add(mIgnoreProjectAction); 265 toolbarManager.add(mAlwaysIgnoreAction); 266 toolbarManager.add(new Separator()); 267 toolbarManager.add(mRemoveAction); 268 toolbarManager.add(mRemoveAllAction); 269 toolbarManager.add(new Separator()); 270 toolbarManager.add(mExpandAll); 271 toolbarManager.add(mCollapseAll); 272 toolbarManager.add(mConfigureColumns); 273 toolbarManager.add(mOptions); 274 } 275 276 @Override setFocus()277 public void setFocus() { 278 mLintView.setFocus(); 279 } 280 281 /** 282 * Sets the resource associated with the lint view 283 * 284 * @param resources the associated resources 285 */ setResources(List<? extends IResource> resources)286 public void setResources(List<? extends IResource> resources) { 287 mLintView.setResources(resources); 288 289 // Refresh the stop/refresh icon status 290 refreshStopIcon(); 291 } 292 refreshStopIcon()293 private void refreshStopIcon() { 294 Job[] currentJobs = LintJob.getCurrentJobs(); 295 if (currentJobs.length > 0) { 296 ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); 297 mRefreshAction.setImageDescriptor(sharedImages.getImageDescriptor( 298 ISharedImages.IMG_ELCL_STOP)); 299 for (Job job : currentJobs) { 300 job.addJobChangeListener(this); 301 } 302 } else { 303 mRefreshAction.setImageDescriptor( 304 IconFactory.getInstance().getImageDescriptor(REFRESH_ICON)); 305 306 } 307 } 308 309 // ---- Implements SelectionListener ---- 310 311 @Override widgetSelected(SelectionEvent e)312 public void widgetSelected(SelectionEvent e) { 313 List<IMarker> markers = mLintView.getSelectedMarkers(); 314 if (markers.size() != 1) { 315 mDetailsText.setText(""); //$NON-NLS-1$ 316 } else { 317 mDetailsText.setText(EclipseLintClient.describe(markers.get(0))); 318 } 319 320 IStatusLineManager status = getViewSite().getActionBars().getStatusLineManager(); 321 status.setMessage(mDetailsText.getText()); 322 323 updateIssueCount(); 324 325 enableActions(markers, true /* updateWidgets */); 326 } 327 enableActions(List<IMarker> markers, boolean updateWidgets)328 private void enableActions(List<IMarker> markers, boolean updateWidgets) { 329 // Update enabled state of actions 330 boolean hasSelection = markers.size() > 0; 331 boolean canFix = hasSelection; 332 for (IMarker marker : markers) { 333 if (!LintFix.hasFix(EclipseLintClient.getId(marker))) { 334 canFix = false; 335 break; 336 } 337 338 // Some fixes cannot be run in bulk 339 if (markers.size() > 1) { 340 List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), marker); 341 if (fixes == null || !fixes.get(0).isBulkCapable()) { 342 canFix = false; 343 break; 344 } 345 } 346 } 347 348 boolean haveFile = false; 349 boolean isJavaOrXml = true; 350 for (IMarker marker : markers) { 351 IResource resource = marker.getResource(); 352 if (resource instanceof IFile || resource instanceof IFolder) { 353 haveFile = true; 354 String name = resource.getName(); 355 if (!LintUtils.endsWith(name, DOT_XML) && !LintUtils.endsWith(name, DOT_JAVA)) { 356 isJavaOrXml = false; 357 } 358 break; 359 } 360 } 361 362 mFixAction.setEnabled(canFix); 363 mIgnoreAction.setEnabled(hasSelection && haveFile && isJavaOrXml); 364 mIgnoreFileAction.setEnabled(hasSelection && haveFile); 365 mIgnoreProjectAction.setEnabled(hasSelection); 366 mAlwaysIgnoreAction.setEnabled(hasSelection); 367 mRemoveAction.setEnabled(hasSelection); 368 369 if (updateWidgets) { 370 getViewSite().getActionBars().getToolBarManager().update(false); 371 } 372 } 373 374 @Override widgetDefaultSelected(SelectionEvent e)375 public void widgetDefaultSelected(SelectionEvent e) { 376 Object source = e.getSource(); 377 if (source == mLintView.getTreeViewer().getControl()) { 378 // Jump to editor 379 List<IMarker> selection = mLintView.getSelectedMarkers(); 380 if (selection.size() > 0) { 381 EclipseLintClient.showMarker(selection.get(0)); 382 } 383 } 384 } 385 386 // --- Implements IJobChangeListener ---- 387 388 @Override done(IJobChangeEvent event)389 public void done(IJobChangeEvent event) { 390 mRefreshAction.setImageDescriptor( 391 IconFactory.getInstance().getImageDescriptor(REFRESH_ICON)); 392 393 if (!mLintView.isDisposed()) { 394 mLintView.getDisplay().asyncExec(new Runnable() { 395 @Override 396 public void run() { 397 if (!mLintView.isDisposed()) { 398 updateIssueCount(); 399 } 400 } 401 }); 402 } 403 } 404 updateIssueCount()405 private void updateIssueCount() { 406 int errors = mLintView.getErrorCount(); 407 int warnings = mLintView.getWarningCount(); 408 mErrorLabel.setText(String.format("%1$d errors, %2$d warnings", errors, warnings)); 409 } 410 411 @Override aboutToRun(IJobChangeEvent event)412 public void aboutToRun(IJobChangeEvent event) { 413 } 414 415 @Override awake(IJobChangeEvent event)416 public void awake(IJobChangeEvent event) { 417 } 418 419 @Override running(IJobChangeEvent event)420 public void running(IJobChangeEvent event) { 421 } 422 423 @Override scheduled(IJobChangeEvent event)424 public void scheduled(IJobChangeEvent event) { 425 } 426 427 @Override sleeping(IJobChangeEvent event)428 public void sleeping(IJobChangeEvent event) { 429 } 430 431 // ---- Actions ---- 432 433 private static final int ACTION_REFRESH = 1; 434 private static final int ACTION_FIX = 2; 435 private static final int ACTION_IGNORE_THIS = 3; 436 private static final int ACTION_IGNORE_FILE = 4; 437 private static final int ACTION_IGNORE_TYPE = 5; 438 private static final int ACTION_IGNORE_ALL = 6; 439 private static final int ACTION_REMOVE = 7; 440 private static final int ACTION_REMOVE_ALL = 8; 441 private static final int ACTION_COLLAPSE = 9; 442 private static final int ACTION_EXPAND = 10; 443 private static final int ACTION_COLUMNS = 11; 444 private static final int ACTION_OPTIONS = 12; 445 446 private class LintViewAction extends Action { 447 448 private final int mAction; 449 LintViewAction(String label, int action, ImageDescriptor imageDesc, ImageDescriptor disabledImageDesc)450 private LintViewAction(String label, int action, 451 ImageDescriptor imageDesc, ImageDescriptor disabledImageDesc) { 452 super(label); 453 mAction = action; 454 setImageDescriptor(imageDesc); 455 if (disabledImageDesc != null) { 456 setDisabledImageDescriptor(disabledImageDesc); 457 } 458 } 459 460 @Override run()461 public void run() { 462 switch (mAction) { 463 case ACTION_REFRESH: { 464 IWorkbench workbench = PlatformUI.getWorkbench(); 465 if (workbench != null) { 466 workbench.saveAllEditors(false /*confirm*/); 467 } 468 469 Job[] jobs = LintJob.getCurrentJobs(); 470 if (jobs.length > 0) { 471 EclipseLintRunner.cancelCurrentJobs(false); 472 } else { 473 List<? extends IResource> resources = mLintView.getResources(); 474 if (resources == null) { 475 return; 476 } 477 Job job = EclipseLintRunner.startLint(resources, null, null, 478 false /*fatalOnly*/, false /*show*/); 479 if (job != null && workbench != null) { 480 job.addJobChangeListener(LintViewPart.this); 481 ISharedImages sharedImages = workbench.getSharedImages(); 482 setImageDescriptor(sharedImages.getImageDescriptor( 483 ISharedImages.IMG_ELCL_STOP)); 484 } 485 } 486 break; 487 } 488 case ACTION_FIX: { 489 List<IMarker> markers = mLintView.getSelectedMarkers(); 490 for (IMarker marker : markers) { 491 List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), 492 marker); 493 if (fixes == null) { 494 continue; 495 } 496 LintFix fix = fixes.get(0); 497 IResource resource = marker.getResource(); 498 if (fix.needsFocus() && resource instanceof IFile) { 499 IRegion region = null; 500 try { 501 int start = marker.getAttribute(IMarker.CHAR_START, -1); 502 int end = marker.getAttribute(IMarker.CHAR_END, -1); 503 if (start != -1) { 504 region = new Region(start, end - start); 505 } 506 AdtPlugin.openFile((IFile) resource, region); 507 } catch (PartInitException e) { 508 AdtPlugin.log(e, "Can't open file %1$s", resource); 509 } 510 } 511 IDocumentProvider provider = new TextFileDocumentProvider(); 512 try { 513 provider.connect(resource); 514 IDocument document = provider.getDocument(resource); 515 if (document != null) { 516 fix.apply(document); 517 if (!fix.needsFocus()) { 518 provider.saveDocument(new NullProgressMonitor(), resource, 519 document, true /*overwrite*/); 520 } 521 } 522 } catch (Exception e) { 523 AdtPlugin.log(e, "Did not find associated editor to apply fix: %1$s", 524 resource.getName()); 525 } finally { 526 provider.disconnect(resource); 527 } 528 } 529 break; 530 } 531 case ACTION_REMOVE: { 532 for (IMarker marker : mLintView.getSelectedMarkers()) { 533 try { 534 marker.delete(); 535 } catch (CoreException e) { 536 AdtPlugin.log(e, null); 537 } 538 } 539 break; 540 } 541 case ACTION_REMOVE_ALL: { 542 List<? extends IResource> resources = mLintView.getResources(); 543 if (resources != null) { 544 for (IResource resource : resources) { 545 EclipseLintClient.clearMarkers(resource); 546 } 547 } 548 break; 549 } 550 case ACTION_IGNORE_ALL: 551 assert false; 552 break; 553 case ACTION_IGNORE_TYPE: 554 case ACTION_IGNORE_FILE: { 555 boolean ignoreInFile = mAction == ACTION_IGNORE_FILE; 556 for (IMarker marker : mLintView.getSelectedMarkers()) { 557 String id = EclipseLintClient.getId(marker); 558 if (id != null) { 559 IResource resource = marker.getResource(); 560 LintFixGenerator.suppressDetector(id, true, 561 ignoreInFile ? resource : resource.getProject(), 562 ignoreInFile); 563 } 564 } 565 break; 566 } 567 case ACTION_IGNORE_THIS: { 568 for (IMarker marker : mLintView.getSelectedMarkers()) { 569 LintFixGenerator.addSuppressAnnotation(marker); 570 } 571 break; 572 } 573 case ACTION_COLLAPSE: { 574 mLintView.collapseAll(); 575 break; 576 } 577 case ACTION_EXPAND: { 578 mLintView.expandAll(); 579 break; 580 } 581 case ACTION_COLUMNS: { 582 mLintView.configureColumns(); 583 break; 584 } 585 case ACTION_OPTIONS: { 586 PreferenceManager manager = new PreferenceManager(); 587 588 LintPreferencePage page = new LintPreferencePage(); 589 String title = "Default/Global Settings"; 590 page.setTitle(title); 591 IPreferenceNode node = new PreferenceNode(title, page); 592 manager.addToRoot(node); 593 594 595 List<? extends IResource> resources = mLintView.getResources(); 596 if (resources != null) { 597 Set<IProject> projects = new HashSet<IProject>(); 598 for (IResource resource : resources) { 599 projects.add(resource.getProject()); 600 } 601 if (projects.size() > 0) { 602 for (IProject project : projects) { 603 page = new LintPreferencePage(); 604 page.setTitle(String.format("Settings for %1$s", 605 project.getName())); 606 page.setElement(project); 607 node = new PreferenceNode(project.getName(), page); 608 manager.addToRoot(node); 609 } 610 } 611 } 612 613 Shell shell = LintViewPart.this.getSite().getShell(); 614 PreferenceDialog dialog = new PreferenceDialog(shell, manager); 615 dialog.create(); 616 dialog.setSelectedNode(title); 617 dialog.open(); 618 break; 619 } 620 default: 621 assert false : mAction; 622 } 623 updateIssueCount(); 624 } 625 } 626 627 /** 628 * Shows or reconfigures the LintView to show the lint warnings for the 629 * given project 630 * 631 * @param projects the projects to show lint warnings for 632 */ show(List<? extends IResource> projects)633 public static void show(List<? extends IResource> projects) { 634 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); 635 if (window != null) { 636 IWorkbenchPage page = window.getActivePage(); 637 if (page != null) { 638 try { 639 // Pass initial project context via static field read by constructor 640 sInitialResources = projects; 641 IViewPart view = page.showView(LintViewPart.ID, null, 642 IWorkbenchPage.VIEW_ACTIVATE); 643 if (sInitialResources != null && view instanceof LintViewPart) { 644 // The view must be showing already since the constructor was not 645 // run, so reconfigure the view instead 646 LintViewPart lintView = (LintViewPart) view; 647 lintView.setResources(projects); 648 } 649 } catch (PartInitException e) { 650 AdtPlugin.log(e, "Cannot open Lint View"); 651 } finally { 652 sInitialResources = null; 653 } 654 } 655 } 656 } 657 } 658