diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java new file mode 100644 index 000000000..366e94945 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java @@ -0,0 +1,226 @@ +/* + * 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.tools.lint.checks.AccessibilityDetector; +import com.android.tools.lint.checks.DetectMissingPrefix; +import com.android.tools.lint.checks.DosLineEndingDetector; +import com.android.tools.lint.checks.HardcodedValuesDetector; +import com.android.tools.lint.checks.InefficientWeightDetector; +import com.android.tools.lint.checks.ManifestDetector; +import com.android.tools.lint.checks.MissingIdDetector; +import com.android.tools.lint.checks.ObsoleteLayoutParamsDetector; +import com.android.tools.lint.checks.PxUsageDetector; +import com.android.tools.lint.checks.ScrollViewChildDetector; +import com.android.tools.lint.checks.SecurityDetector; +import com.android.tools.lint.checks.TextFieldDetector; +import com.android.tools.lint.checks.TranslationDetector; +import com.android.tools.lint.checks.TypoDetector; +import com.android.tools.lint.checks.TypographyDetector; +import com.android.tools.lint.checks.UseCompoundDrawableDetector; +import com.android.tools.lint.checks.UselessViewDetector; +import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.TextFormat; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.contentassist.IContextInformation; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; + +import java.lang.reflect.Constructor; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +abstract class LintFix implements ICompletionProposal { + protected final IMarker mMarker; + protected final String mId; + + protected LintFix(String id, IMarker marker) { + mId = id; + mMarker = marker; + } + + /** + * Returns true if this fix needs focus (which means that when the fix is + * performed from for example a {@link LintListDialog}'s Fix button) the + * editor needs to be given focus. + * + * @return true if this fix needs focus after being applied + */ + public boolean needsFocus() { + return true; + } + + /** + * Returns true if this fix can be performed along side other fixes + * + * @return true if this fix can be performed in a bulk operation with other + * fixes + */ + public boolean isBulkCapable() { + return false; + } + + /** + * Returns true if this fix can be cancelled once it's invoked. This is the case + * for fixes which shows a confirmation dialog (such as the Extract String etc). + * This will be used to determine whether the marker can be deleted immediately + * (for non-cancelable fixes) or if it should be left alone and detected fix + * on the next save. + * + * @return true if the fix can be cancelled + */ + public boolean isCancelable() { + return true; + } + + // ---- Implements ICompletionProposal ---- + + @Override + public String getDisplayString() { + return null; + } + + @Override + public String getAdditionalProposalInfo() { + Issue issue = EclipseLintClient.getRegistry().getIssue(mId); + if (issue != null) { + return issue.getExplanation(TextFormat.HTML); + } + + return null; + } + + public void deleteMarker() { + try { + mMarker.delete(); + } catch (PartInitException e) { + AdtPlugin.log(e, null); + } catch (CoreException e) { + AdtPlugin.log(e, null); + } + } + + @Override + public Point getSelection(IDocument document) { + return null; + } + + @Override + public Image getImage() { + ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); + return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK); + } + + @Override + public IContextInformation getContextInformation() { + return null; + } + + // --- Access to available fixes --- + + private static final Map<String, Class<? extends LintFix>> sFixes = + new HashMap<String, Class<? extends LintFix>>(); + // Keep this map in sync with BuiltinIssueRegistry's hasAutoFix() data + static { + sFixes.put(InefficientWeightDetector.INEFFICIENT_WEIGHT.getId(), + LinearLayoutWeightFix.class); + sFixes.put(AccessibilityDetector.ISSUE.getId(), SetAttributeFix.class); + sFixes.put(InefficientWeightDetector.BASELINE_WEIGHTS.getId(), SetAttributeFix.class); + sFixes.put(ManifestDetector.ALLOW_BACKUP.getId(), SetAttributeFix.class); + sFixes.put(MissingIdDetector.ISSUE.getId(), SetAttributeFix.class); + sFixes.put(HardcodedValuesDetector.ISSUE.getId(), ExtractStringFix.class); + sFixes.put(UselessViewDetector.USELESS_LEAF.getId(), RemoveUselessViewFix.class); + sFixes.put(UselessViewDetector.USELESS_PARENT.getId(), RemoveUselessViewFix.class); + sFixes.put(PxUsageDetector.PX_ISSUE.getId(), ConvertToDpFix.class); + sFixes.put(TextFieldDetector.ISSUE.getId(), SetAttributeFix.class); + sFixes.put(SecurityDetector.EXPORTED_SERVICE.getId(), SetAttributeFix.class); + sFixes.put(TranslationDetector.MISSING.getId(), SetAttributeFix.class); + sFixes.put(DetectMissingPrefix.MISSING_NAMESPACE.getId(), AddPrefixFix.class); + sFixes.put(ScrollViewChildDetector.ISSUE.getId(), SetScrollViewSizeFix.class); + sFixes.put(ObsoleteLayoutParamsDetector.ISSUE.getId(), ObsoleteLayoutParamsFix.class); + sFixes.put(TypographyDetector.DASHES.getId(), TypographyFix.class); + sFixes.put(TypographyDetector.ELLIPSIS.getId(), TypographyFix.class); + sFixes.put(TypographyDetector.FRACTIONS.getId(), TypographyFix.class); + sFixes.put(TypographyDetector.OTHER.getId(), TypographyFix.class); + sFixes.put(TypographyDetector.QUOTES.getId(), TypographyFix.class); + sFixes.put(UseCompoundDrawableDetector.ISSUE.getId(), + UseCompoundDrawableDetectorFix.class); + sFixes.put(TypoDetector.ISSUE.getId(), TypoFix.class); + sFixes.put(DosLineEndingDetector.ISSUE.getId(), DosLineEndingsFix.class); + // ApiDetector.UNSUPPORTED is provided as a marker resolution rather than + // a quick assistant (the marker resolution adds a suitable @TargetApi annotation) + } + + public static boolean hasFix(String id) { + return sFixes.containsKey(id); + } + + /** + * Returns one or more fixes for the given issue, or null if no fixes are available + * + * @param id the id o the issue to obtain a fix for (see {@link Issue#getId()}) + * @param marker the marker corresponding to the error + * @return a nonempty list of fix, or null + */ + @Nullable + public static List<LintFix> getFixes(@NonNull String id, @NonNull IMarker marker) { + Class<? extends LintFix> clazz = sFixes.get(id); + if (clazz != null) { + try { + Constructor<? extends LintFix> constructor = clazz.getDeclaredConstructor( + String.class, IMarker.class); + constructor.setAccessible(true); + LintFix fix = constructor.newInstance(id, marker); + List<LintFix> alternatives = fix.getAllFixes(); + if (alternatives != null) { + return alternatives; + } else { + return Collections.singletonList(fix); + } + } catch (Throwable t) { + AdtPlugin.log(t, null); + } + } + + return null; + } + + /** + * Returns a full list of fixes for this issue. This will produce a list of + * multiple fixes, in the desired order, which provide alternative ways of + * fixing the issue. + * + * @return a list of fixes to fix this issue, or null if there are no + * variations + */ + @Nullable + protected List<LintFix> getAllFixes() { + return null; + } +} |