aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java
diff options
context:
space:
mode:
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.java237
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;
+ }
+}