• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.tools.lint.checks.AccessibilityDetector;
21 import com.android.tools.lint.checks.DetectMissingPrefix;
22 import com.android.tools.lint.checks.HardcodedValuesDetector;
23 import com.android.tools.lint.checks.InefficientWeightDetector;
24 import com.android.tools.lint.checks.ObsoleteLayoutParamsDetector;
25 import com.android.tools.lint.checks.PxUsageDetector;
26 import com.android.tools.lint.checks.ScrollViewChildDetector;
27 import com.android.tools.lint.checks.SecurityDetector;
28 import com.android.tools.lint.checks.TextFieldDetector;
29 import com.android.tools.lint.checks.TypographyDetector;
30 import com.android.tools.lint.checks.UseCompoundDrawableDetector;
31 import com.android.tools.lint.checks.UselessViewDetector;
32 import com.android.tools.lint.detector.api.Issue;
33 
34 import org.eclipse.core.resources.IMarker;
35 import org.eclipse.core.runtime.CoreException;
36 import org.eclipse.jface.text.IDocument;
37 import org.eclipse.jface.text.contentassist.ICompletionProposal;
38 import org.eclipse.jface.text.contentassist.IContextInformation;
39 import org.eclipse.swt.graphics.Image;
40 import org.eclipse.swt.graphics.Point;
41 import org.eclipse.ui.ISharedImages;
42 import org.eclipse.ui.PartInitException;
43 import org.eclipse.ui.PlatformUI;
44 
45 import java.lang.reflect.Constructor;
46 import java.util.HashMap;
47 import java.util.Map;
48 
49 abstract class LintFix implements ICompletionProposal {
50     protected final IMarker mMarker;
51     protected final String mId;
52 
LintFix(String id, IMarker marker)53     protected LintFix(String id, IMarker marker) {
54         mId = id;
55         mMarker = marker;
56     }
57 
58     /**
59      * Returns true if this fix needs focus (which means that when the fix is
60      * performed from for example a {@link LintListDialog}'s Fix button) the
61      * editor needs to be given focus.
62      *
63      * @return true if this fix needs focus after being applied
64      */
needsFocus()65     public boolean needsFocus() {
66         return true;
67     }
68 
69     /**
70      * Returns true if this fix can be performed along side other fixes
71      *
72      * @return true if this fix can be performed in a bulk operation with other
73      *         fixes
74      */
isBulkCapable()75     public boolean isBulkCapable() {
76         return false;
77     }
78 
79     /**
80      * Returns true if this fix can be cancelled once it's invoked. This is the case
81      * for fixes which shows a confirmation dialog (such as the Extract String etc).
82      * This will be used to determine whether the marker can be deleted immediately
83      * (for non-cancelable fixes) or if it should be left alone and detected fix
84      * on the next save.
85      *
86      * @return true if the
87      */
isCancelable()88     public boolean isCancelable() {
89         return true;
90     }
91 
92     // ---- Implements ICompletionProposal ----
93 
94     @Override
getDisplayString()95     public String getDisplayString() {
96         return null;
97     }
98 
99     @Override
getAdditionalProposalInfo()100     public String getAdditionalProposalInfo() {
101         Issue issue = EclipseLintClient.getRegistry().getIssue(mId);
102         if (issue != null) {
103             return issue.getExplanation().replace("\n", "<br>"); //$NON-NLS-1$ //$NON-NLS-2$
104         }
105 
106         return null;
107     }
108 
deleteMarker()109     public void deleteMarker() {
110         try {
111             mMarker.delete();
112         } catch (PartInitException e) {
113             AdtPlugin.log(e, null);
114         } catch (CoreException e) {
115             AdtPlugin.log(e, null);
116         }
117     }
118 
119     @Override
getSelection(IDocument document)120     public Point getSelection(IDocument document) {
121         return null;
122     }
123 
124     @Override
getImage()125     public Image getImage() {
126         ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
127         return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK);
128     }
129 
130     @Override
getContextInformation()131     public IContextInformation getContextInformation() {
132         return null;
133     }
134 
135     // --- Access to available fixes ---
136 
137     private static final Map<String, Class<? extends LintFix>> sFixes =
138             new HashMap<String, Class<? extends LintFix>>();
139     // Keep this map in sync with BuiltinIssueRegistry's hasAutoFix() data
140     static {
InefficientWeightDetector.INEFFICIENT_WEIGHT.getId()141         sFixes.put(InefficientWeightDetector.INEFFICIENT_WEIGHT.getId(),
142                 LinearLayoutWeightFix.class);
AccessibilityDetector.ISSUE.getId()143         sFixes.put(AccessibilityDetector.ISSUE.getId(), SetAttributeFix.class);
InefficientWeightDetector.BASELINE_WEIGHTS.getId()144         sFixes.put(InefficientWeightDetector.BASELINE_WEIGHTS.getId(), SetAttributeFix.class);
HardcodedValuesDetector.ISSUE.getId()145         sFixes.put(HardcodedValuesDetector.ISSUE.getId(), ExtractStringFix.class);
UselessViewDetector.USELESS_LEAF.getId()146         sFixes.put(UselessViewDetector.USELESS_LEAF.getId(), RemoveUselessViewFix.class);
UselessViewDetector.USELESS_PARENT.getId()147         sFixes.put(UselessViewDetector.USELESS_PARENT.getId(), RemoveUselessViewFix.class);
PxUsageDetector.ISSUE.getId()148         sFixes.put(PxUsageDetector.ISSUE.getId(), ConvertToDpFix.class);
TextFieldDetector.ISSUE.getId()149         sFixes.put(TextFieldDetector.ISSUE.getId(), SetAttributeFix.class);
SecurityDetector.EXPORTED_SERVICE.getId()150         sFixes.put(SecurityDetector.EXPORTED_SERVICE.getId(), SetAttributeFix.class);
DetectMissingPrefix.MISSING_NAMESPACE.getId()151         sFixes.put(DetectMissingPrefix.MISSING_NAMESPACE.getId(), AddPrefixFix.class);
ScrollViewChildDetector.ISSUE.getId()152         sFixes.put(ScrollViewChildDetector.ISSUE.getId(), SetScrollViewSizeFix.class);
ObsoleteLayoutParamsDetector.ISSUE.getId()153         sFixes.put(ObsoleteLayoutParamsDetector.ISSUE.getId(), ObsoleteLayoutParamsFix.class);
TypographyDetector.DASHES.getId()154         sFixes.put(TypographyDetector.DASHES.getId(), TypographyFix.class);
TypographyDetector.ELLIPSIS.getId()155         sFixes.put(TypographyDetector.ELLIPSIS.getId(), TypographyFix.class);
TypographyDetector.FRACTIONS.getId()156         sFixes.put(TypographyDetector.FRACTIONS.getId(), TypographyFix.class);
TypographyDetector.OTHER.getId()157         sFixes.put(TypographyDetector.OTHER.getId(), TypographyFix.class);
TypographyDetector.QUOTES.getId()158         sFixes.put(TypographyDetector.QUOTES.getId(), TypographyFix.class);
UseCompoundDrawableDetector.ISSUE.getId()159         sFixes.put(UseCompoundDrawableDetector.ISSUE.getId(),
160                 UseCompoundDrawableDetectorFix.class);
161         // ApiDetector.UNSUPPORTED is provided as a marker resolution rather than
162         // a quick assistant (the marker resolution adds a suitable @TargetApi annotation)
163     }
164 
hasFix(String id)165     public static boolean hasFix(String id) {
166         return sFixes.containsKey(id);
167     }
168 
169     /**
170      * Returns a fix for the given issue, or null if no fix is available
171      *
172      * @param id the id o the issue to obtain a fix for (see {@link Issue#getId()})
173      * @param marker the marker corresponding to the error
174      * @return a fix, or null
175      */
getFix(String id, final IMarker marker)176     public static LintFix getFix(String id, final IMarker marker) {
177         Class<? extends LintFix> clazz = sFixes.get(id);
178         if (clazz != null) {
179             try {
180                 Constructor<? extends LintFix> constructor = clazz.getDeclaredConstructor(
181                         String.class, IMarker.class);
182                 constructor.setAccessible(true);
183                 return constructor.newInstance(id, marker);
184             } catch (Throwable t) {
185                 AdtPlugin.log(t, null);
186             }
187         }
188 
189         return null;
190     }
191 }
192