diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java new file mode 100644 index 000000000..88e0880e5 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2012 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 static com.android.SdkConstants.ATTR_IGNORE; +import static com.android.SdkConstants.ATTR_TARGET_API; +import static com.android.SdkConstants.DOT_XML; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.sdklib.SdkVersionInfo; +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 com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; +import com.android.tools.lint.checks.ApiDetector; +import com.google.common.collect.Lists; + +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.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Fix for adding {@code tools:ignore="id"} attributes in XML files. + */ +class AddSuppressAttribute implements ICompletionProposal { + private final AndroidXmlEditor mEditor; + private final String mId; + private final IMarker mMarker; + private final Element mElement; + private final String mDescription; + /** + * Should it create a {@code tools:targetApi} attribute instead of a + * {@code tools:ignore} attribute? If so pass a non null API level + */ + private final String mTargetApi; + + + private AddSuppressAttribute( + @NonNull AndroidXmlEditor editor, + @NonNull String id, + @NonNull IMarker marker, + @NonNull Element element, + @NonNull String description, + @Nullable String targetApi) { + mEditor = editor; + mId = id; + mMarker = marker; + mElement = element; + mDescription = description; + mTargetApi = targetApi; + } + + @Override + public Point getSelection(IDocument document) { + return null; + } + + @Override + public String getAdditionalProposalInfo() { + return null; + } + + @Override + public String getDisplayString() { + return mDescription; + } + + @Override + public IContextInformation getContextInformation() { + return null; + } + + @Override + public Image getImage() { + return IconFactory.getInstance().getIcon("newannotation"); //$NON-NLS-1$ + } + + @Override + public void apply(IDocument document) { + String attribute; + String value; + if (mTargetApi != null) { + attribute = ATTR_TARGET_API; + value = mTargetApi; + } else { + attribute = ATTR_IGNORE; + value = mId; + } + AdtUtils.setToolsAttribute(mEditor, mElement, mDescription, attribute, value, + true /*reveal*/, true /*append*/); + + try { + // Remove the marker now that the suppress attribute has been added + // (so the user doesn't have to re-run lint just to see it disappear) + mMarker.delete(); + } catch (CoreException e) { + AdtPlugin.log(e, "Could not remove marker"); + } + } + + /** + * Returns a quickfix to suppress a specific lint issue id on the node corresponding to + * the given marker. + * + * @param editor the associated editor containing the marker + * @param marker the marker to create fixes for + * @param id the issue id + * @return a list of fixes for this marker, possibly empty + */ + @NonNull + public static List<AddSuppressAttribute> createFixes( + @NonNull AndroidXmlEditor editor, + @NonNull IMarker marker, + @NonNull String id) { + // This only applies to XML files: + String fileName = marker.getResource().getName(); + if (!fileName.endsWith(DOT_XML)) { + return Collections.emptyList(); + } + + int offset = marker.getAttribute(IMarker.CHAR_START, -1); + Node node; + if (offset == -1) { + node = DomUtilities.getNode(editor.getStructuredDocument(), 0); + if (node != null) { + node = node.getOwnerDocument().getDocumentElement(); + } + } else { + node = DomUtilities.getNode(editor.getStructuredDocument(), offset); + } + if (node == null) { + return Collections.emptyList(); + } + Document document = node.getOwnerDocument(); + while (node != null && node.getNodeType() != Node.ELEMENT_NODE) { + node = node.getParentNode(); + } + if (node == null) { + node = document.getDocumentElement(); + if (node == null) { + return Collections.emptyList(); + } + } + + String desc = String.format("Add ignore '%1$s\' to element", id); + Element element = (Element) node; + List<AddSuppressAttribute> fixes = Lists.newArrayListWithExpectedSize(2); + fixes.add(new AddSuppressAttribute(editor, id, marker, element, desc, null)); + + int api = -1; + if (id.equals(ApiDetector.UNSUPPORTED.getId()) + || id.equals(ApiDetector.INLINED.getId())) { + String message = marker.getAttribute(IMarker.MESSAGE, null); + if (message != null) { + Pattern pattern = Pattern.compile("\\s(\\d+)\\s"); //$NON-NLS-1$ + Matcher matcher = pattern.matcher(message); + if (matcher.find()) { + api = Integer.parseInt(matcher.group(1)); + String targetApi; + String buildCode = SdkVersionInfo.getBuildCode(api); + if (buildCode != null) { + targetApi = buildCode.toLowerCase(Locale.US); + fixes.add(new AddSuppressAttribute(editor, id, marker, element, + String.format("Add targetApi '%1$s\' to element", targetApi), + targetApi)); + } + targetApi = Integer.toString(api); + fixes.add(new AddSuppressAttribute(editor, id, marker, element, + String.format("Add targetApi '%1$s\' to element", targetApi), + targetApi)); + } + } + } + + return fixes; + } + + /** + * Returns a quickfix to suppress a given issue type on the <b>root element</b> + * of the given editor. + * + * @param editor the associated editor containing the marker + * @param marker the marker to create fixes for + * @param id the issue id + * @return a fix for this marker, or null if unable + */ + @Nullable + public static AddSuppressAttribute createFixForAll( + @NonNull AndroidXmlEditor editor, + @NonNull IMarker marker, + @NonNull String id) { + // This only applies to XML files: + String fileName = marker.getResource().getName(); + if (!fileName.endsWith(DOT_XML)) { + return null; + } + + Node node = DomUtilities.getNode(editor.getStructuredDocument(), 0); + if (node != null) { + node = node.getOwnerDocument().getDocumentElement(); + String desc = String.format("Add ignore '%1$s\' to element", id); + Element element = (Element) node; + return new AddSuppressAttribute(editor, id, marker, element, desc, null); + } + + return null; + } +} |