blob: f88c3772cd58878f09b44fefe2c8ac8f79b8eb8b [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
*
* 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.ide.eclipse.adt.internal.lint;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtUtils;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.IconFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@SuppressWarnings("restriction") // WST DOM access
class LintListDialog extends TitleAreaDialog implements SelectionListener {
private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
private final IFile mFile;
private final IEditorPart mEditor;
private Button mFixButton;
private Button mIgnoreButton;
private Button mIgnoreAllButton;
private Button mShowButton;
private Text mDetailsText;
private Button mIgnoreTypeButton;
private LintList mList;
LintListDialog(
@NonNull Shell parentShell,
@NonNull IFile file,
@Nullable IEditorPart editor) {
super(parentShell);
mFile = file;
mEditor = editor;
setHelpAvailable(false);
}
@Override
protected void setShellStyle(int newShellStyle) {
// Allow resize
super.setShellStyle(newShellStyle | SWT.TITLE | SWT.MODELESS | SWT.RESIZE);
}
@Override
public boolean close() {
mList.dispose();
return super.close();
}
@Override
protected Control createContents(Composite parent) {
Control contents = super.createContents(parent);
setTitle("Lint Warnings in Layout");
setMessage("Lint Errors found for the current layout:");
setTitleImage(IconFactory.getInstance().getIcon(PROJECT_LOGO_LARGE));
return contents;
}
@SuppressWarnings("unused") // SWT constructors have side effects, they are not unused
@Override
protected Control createDialogArea(Composite parent) {
Composite area = (Composite) super.createDialogArea(parent);
Composite container = new Composite(area, SWT.NONE);
container.setLayoutData(new GridData(GridData.FILL_BOTH));
container.setLayout(new GridLayout(2, false));
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IWorkbenchPartSite site = null;
if (page.getActivePart() != null) {
site = page.getActivePart().getSite();
}
mList = new LintList(site, container, null /*memento*/, true /*singleFile*/);
mList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 6));
mShowButton = new Button(container, SWT.NONE);
mShowButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
mShowButton.setText("Show");
mShowButton.setToolTipText("Opens the editor to reveal the XML with the issue");
mShowButton.addSelectionListener(this);
mFixButton = new Button(container, SWT.NONE);
mFixButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
mFixButton.setText("Fix");
mFixButton.setToolTipText("Automatically corrects the problem, if possible");
mFixButton.setEnabled(false);
mFixButton.addSelectionListener(this);
mIgnoreButton = new Button(container, SWT.NONE);
mIgnoreButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
mIgnoreButton.setText("Suppress Issue");
mIgnoreButton.setToolTipText("Adds a special attribute in the layout to suppress this specific warning");
mIgnoreButton.addSelectionListener(this);
mIgnoreAllButton = new Button(container, SWT.NONE);
mIgnoreAllButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
mIgnoreAllButton.setText("Suppress in Layout");
mIgnoreAllButton.setEnabled(mEditor instanceof AndroidXmlEditor);
mIgnoreAllButton.setToolTipText("Adds an attribute on the root element to suppress all issues of this type in this layout");
mIgnoreAllButton.addSelectionListener(this);
mIgnoreTypeButton = new Button(container, SWT.NONE);
mIgnoreTypeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
mIgnoreTypeButton.setText("Disable Issue Type");
mIgnoreTypeButton.setToolTipText("Turns off checking for this type of error everywhere");
mIgnoreTypeButton.addSelectionListener(this);
new Label(container, SWT.NONE);
mDetailsText = new Text(container, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP
| SWT.V_SCROLL | SWT.MULTI);
Display display = parent.getDisplay();
mDetailsText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
mDetailsText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
GridData gdText = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
gdText.heightHint = 80;
mDetailsText.setLayoutData(gdText);
new Label(container, SWT.NONE);
mList.addSelectionListener(this);
mList.setResources(Collections.<IResource>singletonList(mFile));
mList.selectFirst();
if (mList.getSelectedMarkers().size() > 0) {
updateSelectionState();
}
return area;
}
/**
* Create contents of the button bar.
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
}
/**
* Return the initial size of the dialog.
*/
@Override
protected Point getInitialSize() {
return new Point(600, 400);
}
private void selectMarker(IMarker marker) {
if (marker == null) {
mDetailsText.setText(""); //$NON-NLS-1$
return;
}
mDetailsText.setText(EclipseLintClient.describe(marker));
}
// ---- Implements SelectionListener ----
@Override
public void widgetSelected(SelectionEvent e) {
Object source = e.getSource();
if (source == mList.getTreeViewer().getControl()) {
// Enable/disable buttons
updateSelectionState();
} else if (source == mShowButton) {
List<IMarker> selection = mList.getSelectedMarkers();
if (selection.size() > 0) {
EclipseLintClient.showMarker(selection.get(0));
}
} else if (source == mFixButton) {
List<IMarker> selection = mList.getSelectedMarkers();
for (IMarker marker : selection) {
List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), marker);
if (fixes == null) {
continue;
}
LintFix fix = fixes.get(0);
IEditorPart editor = AdtUtils.getActiveEditor();
if (editor instanceof AndroidXmlEditor) {
IStructuredDocument doc = ((AndroidXmlEditor) editor).getStructuredDocument();
fix.apply(doc);
if (fix.needsFocus()) {
close();
}
} else {
AdtPlugin.log(IStatus.ERROR, "Did not find associated editor to apply fix");
}
}
} else if (source == mIgnoreTypeButton) {
for (IMarker marker : mList.getSelectedMarkers()) {
String id = EclipseLintClient.getId(marker);
if (id != null) {
LintFixGenerator.suppressDetector(id, true, mFile, true /*all*/);
}
}
} else if (source == mIgnoreButton) {
for (IMarker marker : mList.getSelectedMarkers()) {
LintFixGenerator.addSuppressAnnotation(marker);
}
} else if (source == mIgnoreAllButton) {
Set<String> ids = new HashSet<String>();
for (IMarker marker : mList.getSelectedMarkers()) {
String id = EclipseLintClient.getId(marker);
if (id != null && !ids.contains(id)) {
ids.add(id);
if (mEditor instanceof AndroidXmlEditor) {
AndroidXmlEditor editor = (AndroidXmlEditor) mEditor;
AddSuppressAttribute fix = AddSuppressAttribute.createFixForAll(editor,
marker, id);
if (fix != null) {
IStructuredDocument document = editor.getStructuredDocument();
fix.apply(document);
}
}
}
}
mList.refresh();
}
}
private void updateSelectionState() {
List<IMarker> selection = mList.getSelectedMarkers();
if (selection.size() == 1) {
selectMarker(selection.get(0));
} else {
selectMarker(null);
}
boolean canFix = selection.size() > 0;
for (IMarker marker : selection) {
if (!LintFix.hasFix(EclipseLintClient.getId(marker))) {
canFix = false;
break;
}
// Some fixes cannot be run in bulk
if (selection.size() > 1) {
List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), marker);
if (fixes == null || !fixes.get(0).isBulkCapable()) {
canFix = false;
break;
}
}
}
mFixButton.setEnabled(canFix);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
Object source = e.getSource();
if (source == mList.getTreeViewer().getControl()) {
// Jump to editor
List<IMarker> selection = mList.getSelectedMarkers();
if (selection.size() > 0) {
EclipseLintClient.showMarker(selection.get(0));
close();
}
}
}
}