/* * 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.internal.editors.IconFactory; import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils; import com.android.tools.lint.detector.api.Issue; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.StyledString; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import java.io.File; import java.util.Comparator; /** A column shown in the {@link LintList} */ abstract class LintColumn implements Comparator<IMarker> { protected final LintList mList; protected LintColumn(@NonNull LintList list) { mList = list; } /** @return true if this column should be shown by default */ public boolean isVisibleByDefault() { return true; } /** @return true if this column's text should be left aligned */ public boolean isLeftAligned() { return true; } /** * @return the number of pixels that this column should show by default */ public int getPreferredWidth() { return getPreferredCharWidth() * SwtUtils.getAverageCharWidth(mList.getDisplay(), mList.getTree().getFont()); } /** * @return the number of characters that this column should show by default */ public int getPreferredCharWidth() { return 15; } /** * @return the title of the column */ @NonNull public abstract String getColumnHeaderText(); /** * @return the image of the column, or null */ public Image getColumnHeaderImage() { return null; } /** * @param marker the {@link IMarker} to get the value for * @return the value of this column for the given marker */ public abstract String getValue(@NonNull IMarker marker); /** * @param marker the {@link IMarker} to get the value for * @return the styled value of this column for the given marker */ public StyledString getStyledValue(@NonNull IMarker marker) { return null; } /** * @param marker the {@link IMarker} to get the image for * @return The image for this particular column, or null */ @Nullable public Image getImage(@NonNull IMarker marker) { return null; } /** * @param marker the {@link IMarker} to get the font for * @return The font for this particular column, or null */ @Nullable public Font getFont(@NonNull IMarker marker) { return null; } /** * @return true if the sort should be in ascending order. If false, sort in descending order. */ public boolean isAscending() { return true; } /** * @return true if this column should be visible by default */ public boolean visibleByDefault() { return true; } @Override public int compare(IMarker o1, IMarker o2) { return getValue(o1).compareTo(getValue(o2)); } // Used for default LabelProvider @Override public String toString() { return getColumnHeaderText(); } static class MessageColumn extends LintColumn { public MessageColumn(LintList list) { super(list); } @Override public @NonNull String getColumnHeaderText() { return "Description"; } @Override public int getPreferredCharWidth() { return 80; } @Override public String getValue(@NonNull IMarker marker) { return getStyledValue(marker).toString(); } @Override public StyledString getStyledValue(@NonNull IMarker marker) { StyledString styledString = new StyledString(); String message = marker.getAttribute(IMarker.MESSAGE, ""); styledString.append(message); int count = mList.getCount(marker); if (count > 1) { styledString.append(String.format(" (%2$d items)", message, count), StyledString.COUNTER_STYLER); } return styledString; } @Override public Image getImage(@NonNull IMarker marker) { int severity = marker.getAttribute(IMarker.SEVERITY, 0); ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); switch (severity) { case IMarker.SEVERITY_ERROR: if (LintFix.hasFix(EclipseLintClient.getId(marker))) { return IconFactory.getInstance().getIcon("quickfix_error"); //$NON-NLS-1$ } return sharedImages.getImage(ISharedImages.IMG_OBJS_ERROR_TSK); case IMarker.SEVERITY_WARNING: if (LintFix.hasFix(EclipseLintClient.getId(marker))) { return IconFactory.getInstance().getIcon("quickfix_warning"); //$NON-NLS-1$ } return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK); case IMarker.SEVERITY_INFO: return sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK); default: return null; } } @Override public Font getFont(@NonNull IMarker marker) { int severity = marker.getAttribute(IMarker.SEVERITY, 0); if (severity == IMarker.SEVERITY_ERROR) { return JFaceResources.getFontRegistry().getBold( JFaceResources.DEFAULT_FONT); } return null; } @Override public boolean isAscending() { return false; } @Override public int compare(IMarker marker2, IMarker marker1) { // Reversing order marker1/marker2 here since we want to use a "descending" column // sorting marker to indicate priority. (Note that we return from isAscending too.) String id1 = EclipseLintClient.getId(marker1); String id2 = EclipseLintClient.getId(marker2); if (id1 == null || id2 == null) { return marker1.getResource().getName().compareTo( marker2.getResource().getName()); } Issue issue1 = mList.getIssue(id1); Issue issue2 = mList.getIssue(id2); if (issue1 == null || issue2 == null) { // Unknown issue? Can happen if you have used a third party detector // which is no longer available but which left a persistent marker behind return id1.compareTo(id2); } int delta = mList.getSeverity(issue1).ordinal() - mList.getSeverity(issue2).ordinal(); if (delta != 0) { return delta; } delta = issue2.getPriority() - issue1.getPriority(); if (delta != 0) { return delta; } delta = issue1.getCategory().compareTo(issue2.getCategory()); if (delta != 0) { return delta; } delta = id1.compareTo(id2); if (delta != 0) { return delta; } IResource resource1 = marker1.getResource(); IResource resource2 = marker2.getResource(); IProject project1 = resource1.getProject(); IProject project2 = resource2.getProject(); delta = project1.getName().compareTo(project2.getName()); if (delta != 0) { return delta; } delta = resource1.getName().compareTo(resource2.getName()); if (delta != 0) { return delta; } return marker1.getAttribute(IMarker.LINE_NUMBER, 0) - marker2.getAttribute(IMarker.LINE_NUMBER, 0); } } static class CategoryColumn extends LintColumn { public CategoryColumn(LintList list) { super(list); } @Override public @NonNull String getColumnHeaderText() { return "Category"; } @Override public int getPreferredCharWidth() { return 20; } @Override public String getValue(@NonNull IMarker marker) { Issue issue = mList.getIssue(marker); if (issue != null) { return issue.getCategory().getFullName(); } else { return ""; } } } static class LocationColumn extends LintColumn { public LocationColumn(LintList list) { super(list); } @Override public @NonNull String getColumnHeaderText() { return "Location"; } @Override public int getPreferredCharWidth() { return 35; } @Override public String getValue(@NonNull IMarker marker) { return getStyledValue(marker).toString(); } @Override public StyledString getStyledValue(@NonNull IMarker marker) { StyledString styledString = new StyledString(); // Combined location IResource resource = marker.getResource(); if (resource instanceof IProject) { styledString.append(resource.getName()); } else { // Show location as Parent/File:Line in Project styledString.append(resource.getName()); if (resource instanceof IFile) { int line = marker.getAttribute(IMarker.LINE_NUMBER, -1); if (line > 1) { styledString.append(':').append(Integer.toString(line)); } } else if (resource instanceof IFolder) { styledString.append(File.separatorChar); } if (!(resource.getParent() instanceof IProject)) { styledString.append(" in "); styledString.append(resource.getParent().getName(), StyledString.DECORATIONS_STYLER); } styledString.append(String.format(" (%1$s)", resource.getProject().getName()), StyledString.QUALIFIER_STYLER); } return styledString; } @Override public int compare(IMarker marker1, IMarker marker2) { IResource resource1 = marker1.getResource(); IResource resource2 = marker2.getResource(); IProject project1 = resource1.getProject(); IProject project2 = resource2.getProject(); int delta = project1.getName().compareTo(project2.getName()); if (delta != 0) { return delta; } delta = resource1.getName().compareTo(resource2.getName()); if (delta != 0) { return delta; } return marker1.getAttribute(IMarker.LINE_NUMBER, 0) - marker2.getAttribute(IMarker.LINE_NUMBER, 0); } } static class FileColumn extends LintColumn { public FileColumn(LintList list) { super(list); } @Override public @NonNull String getColumnHeaderText() { return "File"; } @Override public boolean visibleByDefault() { return false; } @Override public int getPreferredCharWidth() { return 12; } @Override public String getValue(@NonNull IMarker marker) { if (marker.getResource() instanceof IFile) { return marker.getResource().getName(); } else { return ""; } } } static class PathColumn extends LintColumn { public PathColumn(LintList list) { super(list); } @Override public @NonNull String getColumnHeaderText() { return "Path"; } @Override public boolean visibleByDefault() { return false; } @Override public int getPreferredCharWidth() { return 25; } @Override public String getValue(@NonNull IMarker marker) { return marker.getResource().getFullPath().toOSString(); } } static class LineColumn extends LintColumn { public LineColumn(LintList list) { super(list); } @Override public @NonNull String getColumnHeaderText() { return "Line"; } @Override public boolean visibleByDefault() { return false; } @Override public boolean isLeftAligned() { return false; } @Override public int getPreferredCharWidth() { return 4; } @Override public String getValue(@NonNull IMarker marker) { int line = getLine(marker); if (line >= 1) { return Integer.toString(line); } else { return ""; } } private int getLine(IMarker marker) { if (marker.getResource() instanceof IFile) { int line = marker.getAttribute(IMarker.LINE_NUMBER, -1); return line; } return -1; } @Override public int compare(IMarker marker1, IMarker marker2) { return getLine(marker1) - getLine(marker2); } } static class PriorityColumn extends LintColumn { public PriorityColumn(LintList list) { super(list); } @Override public @NonNull String getColumnHeaderText() { return "Priority"; } @Override public boolean visibleByDefault() { return false; } @Override public boolean isLeftAligned() { return false; } @Override public int getPreferredCharWidth() { return 2; } @Override public String getValue(@NonNull IMarker marker) { int priority = getPriority(marker); if (priority > 0) { return Integer.toString(priority); } return ""; } private int getPriority(IMarker marker) { Issue issue = mList.getIssue(marker); if (issue != null) { return issue.getPriority(); } return 0; } @Override public int compare(IMarker marker1, IMarker marker2) { return getPriority(marker1) - getPriority(marker2); } @Override public boolean isAscending() { return false; } } }