Home | History | Annotate | Download | only in lint
      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 com.android.annotations.NonNull;
     19 import com.android.annotations.Nullable;
     20 import com.android.ide.eclipse.adt.internal.editors.IconFactory;
     21 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils;
     22 import com.android.tools.lint.detector.api.Issue;
     23 
     24 import org.eclipse.core.resources.IFile;
     25 import org.eclipse.core.resources.IFolder;
     26 import org.eclipse.core.resources.IMarker;
     27 import org.eclipse.core.resources.IProject;
     28 import org.eclipse.core.resources.IResource;
     29 import org.eclipse.jface.resource.JFaceResources;
     30 import org.eclipse.jface.viewers.StyledString;
     31 import org.eclipse.swt.graphics.Font;
     32 import org.eclipse.swt.graphics.Image;
     33 import org.eclipse.ui.ISharedImages;
     34 import org.eclipse.ui.PlatformUI;
     35 
     36 import java.io.File;
     37 import java.util.Comparator;
     38 
     39 /** A column shown in the {@link LintList} */
     40 abstract class LintColumn implements Comparator<IMarker> {
     41     protected final LintList mList;
     42 
     43     protected LintColumn(@NonNull LintList list) {
     44         mList = list;
     45     }
     46 
     47     /** @return true if this column should be shown by default */
     48     public boolean isVisibleByDefault() {
     49         return true;
     50     }
     51 
     52     /** @return true if this column's text should be left aligned */
     53     public boolean isLeftAligned() {
     54         return true;
     55     }
     56 
     57     /**
     58      * @return the number of pixels that this column should show by default
     59      */
     60     public int getPreferredWidth() {
     61         return getPreferredCharWidth() * SwtUtils.getAverageCharWidth(mList.getDisplay(),
     62                 mList.getTree().getFont());
     63     }
     64 
     65     /**
     66      * @return the number of characters that this column should show by default
     67      */
     68     public int getPreferredCharWidth() {
     69         return 15;
     70     }
     71 
     72     /**
     73      * @return the title of the column
     74      */
     75     @NonNull
     76     public abstract String getColumnHeaderText();
     77 
     78     /**
     79      * @return the image of the column, or null
     80      */
     81     public Image getColumnHeaderImage() {
     82         return null;
     83     }
     84 
     85     /**
     86      * @param marker the {@link IMarker} to get the value for
     87      * @return the value of this column for the given marker
     88      */
     89     public abstract String getValue(@NonNull IMarker marker);
     90 
     91     /**
     92      * @param marker the {@link IMarker} to get the value for
     93      * @return the styled value of this column for the given marker
     94      */
     95     public StyledString getStyledValue(@NonNull IMarker marker) {
     96         return null;
     97     }
     98 
     99     /**
    100      * @param marker the {@link IMarker} to get the image for
    101      * @return The image for this particular column, or null
    102      */
    103     @Nullable
    104     public Image getImage(@NonNull IMarker marker) {
    105         return null;
    106     }
    107 
    108     /**
    109      * @param marker the {@link IMarker} to get the font for
    110      * @return The font for this particular column, or null
    111      */
    112     @Nullable
    113     public Font getFont(@NonNull IMarker marker) {
    114         return null;
    115     }
    116 
    117     /**
    118      * @return true if the sort should be in ascending order. If false, sort in descending order.
    119      */
    120     public boolean isAscending() {
    121         return true;
    122     }
    123 
    124     /**
    125      * @return true if this column should be visible by default
    126      */
    127     public boolean visibleByDefault() {
    128         return true;
    129     }
    130 
    131     @Override
    132     public int compare(IMarker o1, IMarker o2) {
    133         return getValue(o1).compareTo(getValue(o2));
    134     }
    135 
    136     // Used for default LabelProvider
    137     @Override
    138     public String toString() {
    139         return getColumnHeaderText();
    140     }
    141 
    142     static class MessageColumn extends LintColumn {
    143 
    144         public MessageColumn(LintList list) {
    145             super(list);
    146         }
    147 
    148         @Override
    149         public @NonNull String getColumnHeaderText() {
    150             return "Description";
    151         }
    152 
    153         @Override
    154         public int getPreferredCharWidth() {
    155             return 80;
    156         }
    157 
    158         @Override
    159         public String getValue(@NonNull IMarker marker) {
    160             return getStyledValue(marker).toString();
    161         }
    162 
    163         @Override
    164         public StyledString getStyledValue(@NonNull IMarker marker) {
    165             StyledString styledString = new StyledString();
    166 
    167             String message = marker.getAttribute(IMarker.MESSAGE, "");
    168             styledString.append(message);
    169 
    170             int count = mList.getCount(marker);
    171             if (count > 1) {
    172                 styledString.append(String.format(" (%2$d items)", message, count),
    173                         StyledString.COUNTER_STYLER);
    174             }
    175 
    176             return styledString;
    177         }
    178 
    179         @Override
    180         public Image getImage(@NonNull IMarker marker) {
    181             int severity = marker.getAttribute(IMarker.SEVERITY, 0);
    182             ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
    183             switch (severity) {
    184                 case IMarker.SEVERITY_ERROR:
    185                     if (LintFix.hasFix(EclipseLintClient.getId(marker))) {
    186                         return IconFactory.getInstance().getIcon("quickfix_error");   //$NON-NLS-1$
    187                     }
    188                     return sharedImages.getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
    189                 case IMarker.SEVERITY_WARNING:
    190                     if (LintFix.hasFix(EclipseLintClient.getId(marker))) {
    191                         return IconFactory.getInstance().getIcon("quickfix_warning"); //$NON-NLS-1$
    192                     }
    193                     return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK);
    194                 case IMarker.SEVERITY_INFO:
    195                     return sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK);
    196                 default:
    197                     return null;
    198             }
    199         }
    200 
    201         @Override
    202         public Font getFont(@NonNull IMarker marker) {
    203             int severity = marker.getAttribute(IMarker.SEVERITY, 0);
    204             if (severity == IMarker.SEVERITY_ERROR) {
    205                 return JFaceResources.getFontRegistry().getBold(
    206                         JFaceResources.DEFAULT_FONT);
    207             }
    208 
    209             return null;
    210         }
    211 
    212         @Override
    213         public boolean isAscending() {
    214             return false;
    215         }
    216 
    217         @Override
    218         public int compare(IMarker marker2, IMarker marker1) {
    219             // Reversing order marker1/marker2 here since we want to use a "descending" column
    220             // sorting marker to indicate priority. (Note that we return from isAscending too.)
    221 
    222             String id1 = EclipseLintClient.getId(marker1);
    223             String id2 = EclipseLintClient.getId(marker2);
    224             if (id1 == null || id2 == null) {
    225                 return marker1.getResource().getName().compareTo(
    226                         marker2.getResource().getName());
    227             }
    228             Issue issue1 = mList.getIssue(id1);
    229             Issue issue2 = mList.getIssue(id2);
    230             if (issue1 == null || issue2 == null) {
    231                 // Unknown issue? Can happen if you have used a third party detector
    232                 // which is no longer available but which left a persistent marker behind
    233                 return id1.compareTo(id2);
    234             }
    235             int delta = mList.getSeverity(issue1).ordinal() -
    236                     mList.getSeverity(issue2).ordinal();
    237             if (delta != 0) {
    238                 return delta;
    239             }
    240             delta = issue2.getPriority() - issue1.getPriority();
    241             if (delta != 0) {
    242                 return delta;
    243             }
    244             delta = issue1.getCategory().compareTo(issue2.getCategory());
    245             if (delta != 0) {
    246                 return delta;
    247             }
    248             delta = id1.compareTo(id2);
    249             if (delta != 0) {
    250                 return delta;
    251             }
    252 
    253             IResource resource1 = marker1.getResource();
    254             IResource resource2 = marker2.getResource();
    255 
    256             IProject project1 = resource1.getProject();
    257             IProject project2 = resource2.getProject();
    258             delta = project1.getName().compareTo(project2.getName());
    259             if (delta != 0) {
    260                 return delta;
    261             }
    262 
    263             delta = resource1.getName().compareTo(resource2.getName());
    264             if (delta != 0) {
    265                 return delta;
    266             }
    267 
    268             return marker1.getAttribute(IMarker.LINE_NUMBER, 0)
    269                     - marker2.getAttribute(IMarker.LINE_NUMBER, 0);
    270         }
    271     }
    272 
    273     static class CategoryColumn extends LintColumn {
    274 
    275         public CategoryColumn(LintList list) {
    276             super(list);
    277         }
    278 
    279         @Override
    280         public @NonNull String getColumnHeaderText() {
    281             return "Category";
    282         }
    283 
    284         @Override
    285         public int getPreferredCharWidth() {
    286             return 20;
    287         }
    288 
    289         @Override
    290         public String getValue(@NonNull IMarker marker) {
    291             Issue issue = mList.getIssue(marker);
    292             if (issue != null) {
    293                 return issue.getCategory().getFullName();
    294             } else {
    295                 return "";
    296             }
    297         }
    298     }
    299 
    300     static class LocationColumn extends LintColumn {
    301         public LocationColumn(LintList list) {
    302             super(list);
    303         }
    304 
    305         @Override
    306         public @NonNull String getColumnHeaderText() {
    307             return "Location";
    308         }
    309 
    310         @Override
    311         public int getPreferredCharWidth() {
    312             return 35;
    313         }
    314 
    315         @Override
    316         public String getValue(@NonNull IMarker marker) {
    317             return getStyledValue(marker).toString();
    318         }
    319 
    320         @Override
    321         public StyledString getStyledValue(@NonNull IMarker marker) {
    322             StyledString styledString = new StyledString();
    323 
    324             // Combined location
    325             IResource resource = marker.getResource();
    326             if (resource instanceof IProject) {
    327                 styledString.append(resource.getName());
    328             } else {
    329                 // Show location as Parent/File:Line in Project
    330                 styledString.append(resource.getName());
    331                 if (resource instanceof IFile) {
    332                     int line = marker.getAttribute(IMarker.LINE_NUMBER, -1);
    333                     if (line > 1) {
    334                         styledString.append(':').append(Integer.toString(line));
    335                     }
    336                 } else if (resource instanceof IFolder) {
    337                     styledString.append(File.separatorChar);
    338                 }
    339 
    340                 if (!(resource.getParent() instanceof IProject)) {
    341                     styledString.append(" in ");
    342                     styledString.append(resource.getParent().getName(),
    343                             StyledString.DECORATIONS_STYLER);
    344                 }
    345 
    346                 styledString.append(String.format(" (%1$s)", resource.getProject().getName()),
    347                         StyledString.QUALIFIER_STYLER);
    348             }
    349 
    350             return styledString;
    351         }
    352 
    353         @Override
    354         public int compare(IMarker marker1, IMarker marker2) {
    355             IResource resource1 = marker1.getResource();
    356             IResource resource2 = marker2.getResource();
    357 
    358             IProject project1 = resource1.getProject();
    359             IProject project2 = resource2.getProject();
    360             int delta = project1.getName().compareTo(project2.getName());
    361             if (delta != 0) {
    362                 return delta;
    363             }
    364 
    365             delta = resource1.getName().compareTo(resource2.getName());
    366             if (delta != 0) {
    367                 return delta;
    368             }
    369 
    370             return marker1.getAttribute(IMarker.LINE_NUMBER, 0)
    371                     - marker2.getAttribute(IMarker.LINE_NUMBER, 0);
    372         }
    373     }
    374 
    375     static class FileColumn extends LintColumn {
    376         public FileColumn(LintList list) {
    377             super(list);
    378         }
    379 
    380         @Override
    381         public @NonNull String getColumnHeaderText() {
    382             return "File";
    383         }
    384 
    385         @Override
    386         public boolean visibleByDefault() {
    387             return false;
    388         }
    389 
    390         @Override
    391         public int getPreferredCharWidth() {
    392             return 12;
    393         }
    394 
    395         @Override
    396         public String getValue(@NonNull IMarker marker) {
    397             if (marker.getResource() instanceof IFile) {
    398                 return marker.getResource().getName();
    399             } else {
    400                 return "";
    401             }
    402         }
    403     }
    404 
    405     static class PathColumn extends LintColumn {
    406         public PathColumn(LintList list) {
    407             super(list);
    408         }
    409 
    410         @Override
    411         public @NonNull String getColumnHeaderText() {
    412             return "Path";
    413         }
    414 
    415         @Override
    416         public boolean visibleByDefault() {
    417             return false;
    418         }
    419 
    420         @Override
    421         public int getPreferredCharWidth() {
    422             return 25;
    423         }
    424 
    425         @Override
    426         public String getValue(@NonNull IMarker marker) {
    427             return marker.getResource().getFullPath().toOSString();
    428         }
    429     }
    430 
    431     static class LineColumn extends LintColumn {
    432         public LineColumn(LintList list) {
    433             super(list);
    434         }
    435 
    436         @Override
    437         public @NonNull String getColumnHeaderText() {
    438             return "Line";
    439         }
    440 
    441         @Override
    442         public boolean visibleByDefault() {
    443             return false;
    444         }
    445 
    446         @Override
    447         public boolean isLeftAligned() {
    448             return false;
    449         }
    450 
    451         @Override
    452         public int getPreferredCharWidth() {
    453             return 4;
    454         }
    455 
    456         @Override
    457         public String getValue(@NonNull IMarker marker) {
    458             int line = getLine(marker);
    459             if (line >= 1) {
    460                 return Integer.toString(line);
    461             } else {
    462                 return "";
    463             }
    464         }
    465 
    466         private int getLine(IMarker marker) {
    467             if (marker.getResource() instanceof IFile) {
    468                 int line = marker.getAttribute(IMarker.LINE_NUMBER, -1);
    469                 return line;
    470             }
    471 
    472             return -1;
    473         }
    474         @Override
    475         public int compare(IMarker marker1, IMarker marker2) {
    476             return getLine(marker1) - getLine(marker2);
    477         }
    478     }
    479 
    480     static class PriorityColumn extends LintColumn {
    481         public PriorityColumn(LintList list) {
    482             super(list);
    483         }
    484 
    485         @Override
    486         public @NonNull String getColumnHeaderText() {
    487             return "Priority";
    488         }
    489 
    490         @Override
    491         public boolean visibleByDefault() {
    492             return false;
    493         }
    494 
    495         @Override
    496         public boolean isLeftAligned() {
    497             return false;
    498         }
    499 
    500         @Override
    501         public int getPreferredCharWidth() {
    502             return 2;
    503         }
    504 
    505         @Override
    506         public String getValue(@NonNull IMarker marker) {
    507             int priority = getPriority(marker);
    508             if (priority > 0) {
    509                 return Integer.toString(priority);
    510             }
    511             return "";
    512         }
    513 
    514         private int getPriority(IMarker marker) {
    515             Issue issue = mList.getIssue(marker);
    516             if (issue != null) {
    517                 return issue.getPriority();
    518             }
    519             return 0;
    520         }
    521 
    522         @Override
    523         public int compare(IMarker marker1, IMarker marker2) {
    524             return getPriority(marker1) - getPriority(marker2);
    525         }
    526 
    527         @Override
    528         public boolean isAscending() {
    529             return false;
    530         }
    531     }
    532 }