diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint')
34 files changed, 0 insertions, 8097 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddPrefixFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddPrefixFix.java deleted file mode 100644 index d8ce657db..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddPrefixFix.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.ANDROID_URI; - -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.utils.XmlUtils; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Node; - -@SuppressWarnings("restriction") // DOM model -final class AddPrefixFix extends DocumentFix { - private AddPrefixFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - String prefix = XmlUtils.lookupNamespacePrefix(node, ANDROID_URI); - try { - document.replace(start, 0, prefix + ':'); - } catch (BadLocationException e) { - AdtPlugin.log(e, null); - } - } - - @Override - public String getDisplayString() { - return "Add in an Android namespace prefix"; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_OBJ_ADD); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAnnotation.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAnnotation.java deleted file mode 100644 index 1a7fe5697..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAnnotation.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * 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.FQCN_SUPPRESS_LINT; -import static com.android.SdkConstants.FQCN_TARGET_API; -import static com.android.SdkConstants.SUPPRESS_LINT; -import static com.android.SdkConstants.TARGET_API; -import static org.eclipse.jdt.core.dom.ArrayInitializer.EXPRESSIONS_PROPERTY; -import static org.eclipse.jdt.core.dom.SingleMemberAnnotation.VALUE_PROPERTY; - -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.IconFactory; -import com.android.tools.lint.checks.AnnotationDetector; -import com.android.tools.lint.checks.ApiDetector; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.Scope; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; -import org.eclipse.jdt.core.dom.ArrayInitializer; -import org.eclipse.jdt.core.dom.BodyDeclaration; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.FieldDeclaration; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.NodeFinder; -import org.eclipse.jdt.core.dom.SingleMemberAnnotation; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; -import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; -import org.eclipse.jdt.core.dom.rewrite.ListRewrite; -import org.eclipse.jdt.ui.IWorkingCopyManager; -import org.eclipse.jdt.ui.JavaUI; -import org.eclipse.jdt.ui.SharedASTProvider; -import org.eclipse.jface.text.IDocument; -import org.eclipse.swt.graphics.Image; -import org.eclipse.text.edits.MultiTextEdit; -import org.eclipse.text.edits.TextEdit; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IMarkerResolution; -import org.eclipse.ui.IMarkerResolution2; -import org.eclipse.ui.texteditor.IDocumentProvider; -import org.eclipse.ui.texteditor.ITextEditor; - -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Marker resolution for adding {@code @SuppressLint} annotations in Java files. - * It can also add {@code @TargetApi} annotations. - */ -class AddSuppressAnnotation implements IMarkerResolution2 { - private final IMarker mMarker; - private final String mId; - private final BodyDeclaration mNode; - private final String mDescription; - /** - * Should it create a {@code @TargetApi} annotation instead of - * {@code SuppressLint} ? If so pass a non null API level - */ - private final String mTargetApi; - - private AddSuppressAnnotation( - @NonNull String id, - @NonNull IMarker marker, - @NonNull BodyDeclaration node, - @NonNull String description, - @Nullable String targetApi) { - mId = id; - mMarker = marker; - mNode = node; - mDescription = description; - mTargetApi = targetApi; - } - - @Override - public String getLabel() { - return mDescription; - } - - @Override - public String getDescription() { - return null; - } - - @Override - public Image getImage() { - return IconFactory.getInstance().getIcon("newannotation"); //$NON-NLS-1$ - } - - @Override - public void run(IMarker marker) { - ITextEditor textEditor = AdtUtils.getActiveTextEditor(); - IDocumentProvider provider = textEditor.getDocumentProvider(); - IEditorInput editorInput = textEditor.getEditorInput(); - IDocument document = provider.getDocument(editorInput); - if (document == null) { - return; - } - IWorkingCopyManager manager = JavaUI.getWorkingCopyManager(); - ICompilationUnit compilationUnit = manager.getWorkingCopy(editorInput); - try { - MultiTextEdit edit; - if (mTargetApi == null) { - edit = addSuppressAnnotation(document, compilationUnit, mNode); - } else { - edit = addTargetApiAnnotation(document, compilationUnit, mNode); - } - if (edit != null) { - edit.apply(document); - - // Remove the marker now that the suppress annotation has been added - // (so the user doesn't have to re-run lint just to see it disappear, - // and besides we don't want to keep offering marker resolutions on this - // marker which could lead to duplicate annotations since the above code - // assumes that the current id isn't in the list of values, since otherwise - // lint shouldn't have complained here. - mMarker.delete(); - } - } catch (Exception ex) { - AdtPlugin.log(ex, "Could not add suppress annotation"); - } - } - - @SuppressWarnings({"rawtypes"}) // Java AST API has raw types - private MultiTextEdit addSuppressAnnotation( - IDocument document, - ICompilationUnit compilationUnit, - BodyDeclaration declaration) throws CoreException { - List modifiers = declaration.modifiers(); - SingleMemberAnnotation existing = null; - for (Object o : modifiers) { - if (o instanceof SingleMemberAnnotation) { - SingleMemberAnnotation annotation = (SingleMemberAnnotation) o; - String type = annotation.getTypeName().getFullyQualifiedName(); - if (type.equals(FQCN_SUPPRESS_LINT) || type.endsWith(SUPPRESS_LINT)) { - existing = annotation; - break; - } - } - } - - ImportRewrite importRewrite = ImportRewrite.create(compilationUnit, true); - String local = importRewrite.addImport(FQCN_SUPPRESS_LINT); - AST ast = declaration.getAST(); - ASTRewrite rewriter = ASTRewrite.create(ast); - if (existing == null) { - SingleMemberAnnotation newAnnotation = ast.newSingleMemberAnnotation(); - newAnnotation.setTypeName(ast.newSimpleName(local)); - StringLiteral value = ast.newStringLiteral(); - value.setLiteralValue(mId); - newAnnotation.setValue(value); - ListRewrite listRewrite = rewriter.getListRewrite(declaration, - declaration.getModifiersProperty()); - listRewrite.insertFirst(newAnnotation, null); - } else { - Expression existingValue = existing.getValue(); - if (existingValue instanceof StringLiteral) { - StringLiteral stringLiteral = (StringLiteral) existingValue; - if (mId.equals(stringLiteral.getLiteralValue())) { - // Already contains the id - return null; - } - // Create a new array initializer holding the old string plus the new id - ArrayInitializer array = ast.newArrayInitializer(); - StringLiteral old = ast.newStringLiteral(); - old.setLiteralValue(stringLiteral.getLiteralValue()); - array.expressions().add(old); - StringLiteral value = ast.newStringLiteral(); - value.setLiteralValue(mId); - array.expressions().add(value); - rewriter.set(existing, VALUE_PROPERTY, array, null); - } else if (existingValue instanceof ArrayInitializer) { - // Existing array: just append the new string - ArrayInitializer array = (ArrayInitializer) existingValue; - List expressions = array.expressions(); - if (expressions != null) { - for (Object o : expressions) { - if (o instanceof StringLiteral) { - if (mId.equals(((StringLiteral)o).getLiteralValue())) { - // Already contains the id - return null; - } - } - } - } - StringLiteral value = ast.newStringLiteral(); - value.setLiteralValue(mId); - ListRewrite listRewrite = rewriter.getListRewrite(array, EXPRESSIONS_PROPERTY); - listRewrite.insertLast(value, null); - } else { - assert false : existingValue; - return null; - } - } - - TextEdit importEdits = importRewrite.rewriteImports(new NullProgressMonitor()); - TextEdit annotationEdits = rewriter.rewriteAST(document, null); - - // Apply to the document - MultiTextEdit edit = new MultiTextEdit(); - // Create the edit to change the imports, only if - // anything changed - if (importEdits.hasChildren()) { - edit.addChild(importEdits); - } - edit.addChild(annotationEdits); - - return edit; - } - - @SuppressWarnings({"rawtypes"}) // Java AST API has raw types - private MultiTextEdit addTargetApiAnnotation( - IDocument document, - ICompilationUnit compilationUnit, - BodyDeclaration declaration) throws CoreException { - List modifiers = declaration.modifiers(); - SingleMemberAnnotation existing = null; - for (Object o : modifiers) { - if (o instanceof SingleMemberAnnotation) { - SingleMemberAnnotation annotation = (SingleMemberAnnotation) o; - String type = annotation.getTypeName().getFullyQualifiedName(); - if (type.equals(FQCN_TARGET_API) || type.endsWith(TARGET_API)) { - existing = annotation; - break; - } - } - } - - ImportRewrite importRewrite = ImportRewrite.create(compilationUnit, true); - importRewrite.addImport("android.os.Build"); //$NON-NLS-1$ - String local = importRewrite.addImport(FQCN_TARGET_API); - AST ast = declaration.getAST(); - ASTRewrite rewriter = ASTRewrite.create(ast); - if (existing == null) { - SingleMemberAnnotation newAnnotation = ast.newSingleMemberAnnotation(); - newAnnotation.setTypeName(ast.newSimpleName(local)); - Expression value = createLiteral(ast); - newAnnotation.setValue(value); - ListRewrite listRewrite = rewriter.getListRewrite(declaration, - declaration.getModifiersProperty()); - listRewrite.insertFirst(newAnnotation, null); - } else { - Expression value = createLiteral(ast); - rewriter.set(existing, VALUE_PROPERTY, value, null); - } - - TextEdit importEdits = importRewrite.rewriteImports(new NullProgressMonitor()); - TextEdit annotationEdits = rewriter.rewriteAST(document, null); - MultiTextEdit edit = new MultiTextEdit(); - if (importEdits.hasChildren()) { - edit.addChild(importEdits); - } - edit.addChild(annotationEdits); - - return edit; - } - - private Expression createLiteral(AST ast) { - Expression value; - if (!isCodeName()) { - value = ast.newQualifiedName( - ast.newQualifiedName(ast.newSimpleName("Build"), //$NON-NLS-1$ - ast.newSimpleName("VERSION_CODES")), //$NON-NLS-1$ - ast.newSimpleName(mTargetApi)); - } else { - value = ast.newNumberLiteral(mTargetApi); - } - return value; - } - - private boolean isCodeName() { - return Character.isDigit(mTargetApi.charAt(0)); - } - - /** - * Adds any applicable suppress lint fix resolutions into the given list - * - * @param marker the marker to create fixes for - * @param id the issue id - * @param resolutions a list to add the created resolutions into, if any - */ - public static void createFixes(IMarker marker, String id, - List<IMarkerResolution> resolutions) { - ITextEditor textEditor = AdtUtils.getActiveTextEditor(); - IDocumentProvider provider = textEditor.getDocumentProvider(); - IEditorInput editorInput = textEditor.getEditorInput(); - IDocument document = provider.getDocument(editorInput); - if (document == null) { - return; - } - - IWorkingCopyManager manager = JavaUI.getWorkingCopyManager(); - ICompilationUnit compilationUnit = manager.getWorkingCopy(editorInput); - int offset = 0; - int length = 0; - int start = marker.getAttribute(IMarker.CHAR_START, -1); - int end = marker.getAttribute(IMarker.CHAR_END, -1); - offset = start; - length = end - start; - CompilationUnit root = SharedASTProvider.getAST(compilationUnit, - SharedASTProvider.WAIT_YES, null); - if (root == null) { - return; - } - - 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)); - } - } - } - - Issue issue = EclipseLintClient.getRegistry().getIssue(id); - boolean isClassDetector = issue != null && issue.getImplementation().getScope().contains( - Scope.CLASS_FILE); - - // Don't offer to suppress (with an annotation) the annotation checks - if (issue == AnnotationDetector.ISSUE) { - return; - } - - NodeFinder nodeFinder = new NodeFinder(root, offset, length); - ASTNode coveringNode; - if (offset <= 0) { - // Error added on the first line of a Java class: typically from a class-based - // detector which lacks line information. Map this to the top level class - // in the file instead. - coveringNode = root; - if (root.types() != null && root.types().size() > 0) { - Object type = root.types().get(0); - if (type instanceof ASTNode) { - coveringNode = (ASTNode) type; - } - } - } else { - coveringNode = nodeFinder.getCoveringNode(); - } - for (ASTNode body = coveringNode; body != null; body = body.getParent()) { - if (body instanceof BodyDeclaration) { - BodyDeclaration declaration = (BodyDeclaration) body; - - String target = null; - if (body instanceof MethodDeclaration) { - target = ((MethodDeclaration) body).getName().toString() + "()"; //$NON-NLS-1$ - } else if (body instanceof FieldDeclaration) { - target = "field"; - FieldDeclaration field = (FieldDeclaration) body; - if (field.fragments() != null && field.fragments().size() > 0) { - ASTNode first = (ASTNode) field.fragments().get(0); - if (first instanceof VariableDeclarationFragment) { - VariableDeclarationFragment decl = (VariableDeclarationFragment) first; - target = decl.getName().toString(); - } - } - } else if (body instanceof AnonymousClassDeclaration) { - target = "anonymous class"; - } else if (body instanceof TypeDeclaration) { - target = ((TypeDeclaration) body).getName().toString(); - } else { - target = body.getClass().getSimpleName(); - } - - // In class files, detectors can only find annotations on methods - // and on classes, not on variable declarations - if (isClassDetector && !(body instanceof MethodDeclaration - || body instanceof TypeDeclaration - || body instanceof AnonymousClassDeclaration - || body instanceof FieldDeclaration)) { - continue; - } - - String desc = String.format("Add @SuppressLint '%1$s\' to '%2$s'", id, target); - resolutions.add(new AddSuppressAnnotation(id, marker, declaration, desc, null)); - - if (api != -1 - // @TargetApi is only valid on methods and classes, not fields etc - && (body instanceof MethodDeclaration - || body instanceof TypeDeclaration)) { - String apiString = SdkVersionInfo.getBuildCode(api); - if (apiString == null) { - apiString = Integer.toString(api); - } - desc = String.format("Add @TargetApi(%1$s) to '%2$s'", apiString, target); - resolutions.add(new AddSuppressAnnotation(id, marker, declaration, desc, - apiString)); - } - } - } - } -} 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 deleted file mode 100644 index 88e0880e5..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/AddSuppressAttribute.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * 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; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ClearLintMarkersAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ClearLintMarkersAction.java deleted file mode 100644 index a10d39472..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ClearLintMarkersAction.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 org.eclipse.core.resources.IProject; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.ui.IActionDelegate; - -import java.util.List; - -/** Action which clear lint markers from the current project */ -public class ClearLintMarkersAction implements IActionDelegate { - - private ISelection mSelection; - - @Override - public void selectionChanged(IAction action, ISelection selection) { - mSelection = selection; - } - - @Override - public void run(IAction action) { - List<IProject> projects = RunLintAction.getProjects(mSelection, false /*warn*/); - if (projects != null) { - EclipseLintRunner.cancelCurrentJobs(false); - EclipseLintClient.clearMarkers(projects); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ColumnDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ColumnDialog.java deleted file mode 100644 index be987d498..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ColumnDialog.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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.ide.eclipse.adt.AdtPlugin; - -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.ui.dialogs.SelectionStatusDialog; - -/** - * Dialog for editing visible columns in the {@link LintList} - */ -class ColumnDialog extends SelectionStatusDialog implements Listener, IStructuredContentProvider { - private LintColumn[] mColumns; - private LintColumn[] mSelectedColumns; - private CheckboxTableViewer mViewer; - - public ColumnDialog(Shell parent, LintColumn[] fields, LintColumn[] selected) { - super(parent); - mColumns = fields; - mSelectedColumns = selected; - setTitle("Select Visible Columns"); - setHelpAvailable(false); - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite container = new Composite(parent, SWT.NONE); - container.setLayout(new GridLayout(1, false)); - GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); - // Wide enough to accommodate the error label - gridData.widthHint = 500; - container.setLayoutData(gridData); - - Label lblSelectVisibleColumns = new Label(container, SWT.NONE); - lblSelectVisibleColumns.setText("Select visible columns:"); - - mViewer = CheckboxTableViewer.newCheckList(container, - SWT.BORDER | SWT.FULL_SELECTION | SWT.HIDE_SELECTION); - Table table = mViewer.getTable(); - table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - mViewer.setContentProvider(this); - - mViewer.setInput(mColumns); - mViewer.setCheckedElements(mSelectedColumns); - - validate(); - - return container; - } - - @Override - protected void computeResult() { - Object[] checked = mViewer.getCheckedElements(); - mSelectedColumns = new LintColumn[checked.length]; - for (int i = 0, n = checked.length; i < n; i++) { - mSelectedColumns[i] = (LintColumn) checked[i]; - } - } - - public LintColumn[] getSelectedColumns() { - return mSelectedColumns; - } - - @Override - public void handleEvent(Event event) { - validate(); - } - - private void validate() { - IStatus status; - computeResult(); - - if (mViewer.getCheckedElements().length <= 1) { - status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, - "Must selected at least one column"); - } else { - status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID, null); - } - updateStatus(status); - } - - // ---- Implements IStructuredContentProvider ---- - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - @Override - public Object[] getElements(Object inputElement) { - return mColumns; - } - }
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ConvertToDpFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ConvertToDpFix.java deleted file mode 100644 index 628972f8c..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ConvertToDpFix.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.UNIT_PX; -import static com.android.SdkConstants.VALUE_N_DP; - -import com.android.ide.eclipse.adt.AdtPlugin; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.dialogs.IInputValidator; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -@SuppressWarnings("restriction") // DOM model -final class ConvertToDpFix extends DocumentFix implements IInputValidator { - private ConvertToDpFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return true; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - Shell shell = AdtPlugin.getShell(); - InputDensityDialog densityDialog = new InputDensityDialog(shell); - if (densityDialog.open() == Window.OK) { - int dpi = densityDialog.getDensity(); - Element element = (Element) node; - Pattern pattern = Pattern.compile("(\\d+)px"); //$NON-NLS-1$ - NamedNodeMap attributes = element.getAttributes(); - for (int i = 0, n = attributes.getLength(); i < n; i++) { - Attr attribute = (Attr) attributes.item(i); - String value = attribute.getValue(); - if (value.endsWith(UNIT_PX)) { - Matcher matcher = pattern.matcher(value); - if (matcher.matches()) { - String numberString = matcher.group(1); - try { - int px = Integer.parseInt(numberString); - int dp = px * 160 / dpi; - String newValue = String.format(VALUE_N_DP, dp); - attribute.setNodeValue(newValue); - } catch (NumberFormatException nufe) { - AdtPlugin.log(nufe, null); - } - } - } - } - } - } - - @Override - public String getDisplayString() { - return "Convert to \"dp\"..."; - } - - @Override - public Image getImage() { - return AdtPlugin.getAndroidLogo(); - } - - // ---- Implements IInputValidator ---- - - @Override - public String isValid(String input) { - if (input == null || input.length() == 0) - return " "; //$NON-NLS-1$ - - try { - int i = Integer.parseInt(input); - if (i <= 0 || i > 1000) { - return "Invalid range"; - } - } catch (NumberFormatException x) { - return "Enter a valid number"; - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/DocumentFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/DocumentFix.java deleted file mode 100644 index e17d5ec97..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/DocumentFix.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.w3c.dom.Node; - -@SuppressWarnings("restriction") // DOM model -abstract class DocumentFix extends LintFix { - - protected DocumentFix(String id, IMarker marker) { - super(id, marker); - } - - protected abstract void apply(IDocument document, IStructuredModel model, Node node, - int start, int end); - - @Override - public void apply(IDocument document) { - if (!(document instanceof IStructuredDocument)) { - AdtPlugin.log(null, "Unexpected document type: %1$s. Can't fix.", - document.getClass().getName()); - return; - } - int start = mMarker.getAttribute(IMarker.CHAR_START, -1); - int end = mMarker.getAttribute(IMarker.CHAR_END, -1); - if (start != -1 && end != -1) { - IModelManager manager = StructuredModelManager.getModelManager(); - IStructuredModel model = manager.getModelForEdit((IStructuredDocument) document); - Node node = DomUtilities.getNode(document, start); - try { - apply(document, model, node, start, end); - } finally { - model.releaseFromEdit(); - } - - if (!isCancelable()) { - deleteMarker(); - } - } - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/DosLineEndingsFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/DosLineEndingsFix.java deleted file mode 100644 index 9a5456b56..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/DosLineEndingsFix.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtPlugin; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; - -/** Quickfix for correcting line endings in the file */ -class DosLineEndingsFix extends LintFix { - - protected DosLineEndingsFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - public String getDisplayString() { - return "Fix line endings"; - } - - @Override - public void apply(IDocument document) { - char next = 0; - for (int i = document.getLength() - 1; i >= 0; i--) { - try { - char c = document.getChar(i); - if (c == '\r' && next != '\n') { - document.replace(i, 1, "\n"); //$NON-NLS-1$ - } - next = c; - } catch (BadLocationException e) { - AdtPlugin.log(e, null); - return; - } - } - - deleteMarker(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java deleted file mode 100644 index 3dd424087..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java +++ /dev/null @@ -1,1306 +0,0 @@ -/* - * 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 static com.android.SdkConstants.DOT_JAR; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.FD_NATIVE_LIBS; -import static com.android.ide.eclipse.adt.AdtConstants.MARKER_LINT; -import static com.android.ide.eclipse.adt.AdtUtils.workspacePathToFile; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; -import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.sdklib.IAndroidTarget; -import com.android.tools.lint.checks.BuiltinIssueRegistry; -import com.android.tools.lint.client.api.Configuration; -import com.android.tools.lint.client.api.IssueRegistry; -import com.android.tools.lint.client.api.JavaParser; -import com.android.tools.lint.client.api.LintClient; -import com.android.tools.lint.client.api.LintDriver; -import com.android.tools.lint.client.api.XmlParser; -import com.android.tools.lint.detector.api.ClassContext; -import com.android.tools.lint.detector.api.Context; -import com.android.tools.lint.detector.api.DefaultPosition; -import com.android.tools.lint.detector.api.Detector; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.JavaContext; -import com.android.tools.lint.detector.api.LintUtils; -import com.android.tools.lint.detector.api.Location; -import com.android.tools.lint.detector.api.Location.Handle; -import com.android.tools.lint.detector.api.Position; -import com.android.tools.lint.detector.api.Project; -import com.android.tools.lint.detector.api.Severity; -import com.android.tools.lint.detector.api.TextFormat; -import com.android.tools.lint.detector.api.XmlContext; -import com.android.utils.Pair; -import com.android.utils.SdkUtils; -import com.google.common.collect.Maps; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.ITypeHierarchy; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.internal.compiler.CompilationResult; -import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; -import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; -import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.eclipse.jdt.internal.compiler.parser.Parser; -import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; -import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; -import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.editors.text.TextFileDocumentProvider; -import org.eclipse.ui.ide.IDE; -import org.eclipse.ui.texteditor.IDocumentProvider; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; - -import lombok.ast.ecj.EcjTreeConverter; -import lombok.ast.grammar.ParseProblem; -import lombok.ast.grammar.Source; - -/** - * Eclipse implementation for running lint on workspace files and projects. - */ -@SuppressWarnings("restriction") // DOM model -public class EclipseLintClient extends LintClient { - static final String MARKER_CHECKID_PROPERTY = "checkid"; //$NON-NLS-1$ - private static final String MODEL_PROPERTY = "model"; //$NON-NLS-1$ - private final List<? extends IResource> mResources; - private final IDocument mDocument; - private boolean mWasFatal; - private boolean mFatalOnly; - private EclipseJavaParser mJavaParser; - private boolean mCollectNodes; - private Map<Node, IMarker> mNodeMap; - - /** - * Creates a new {@link EclipseLintClient}. - * - * @param registry the associated detector registry - * @param resources the associated resources (project, file or null) - * @param document the associated document, or null if the {@code resource} - * param is not a file - * @param fatalOnly whether only fatal issues should be reported (and therefore checked) - */ - public EclipseLintClient(IssueRegistry registry, List<? extends IResource> resources, - IDocument document, boolean fatalOnly) { - mResources = resources; - mDocument = document; - mFatalOnly = fatalOnly; - } - - /** - * Returns true if lint should only check fatal issues - * - * @return true if lint should only check fatal issues - */ - public boolean isFatalOnly() { - return mFatalOnly; - } - - /** - * Sets whether the lint client should store associated XML nodes for each - * reported issue - * - * @param collectNodes if true, collect node positions for errors in XML - * files, retrievable via the {@link #getIssueForNode} method - */ - public void setCollectNodes(boolean collectNodes) { - mCollectNodes = collectNodes; - } - - /** - * Returns one of the issues for the given node (there could be more than one) - * - * @param node the node to look up lint issues for - * @return the marker for one of the issues found for the given node - */ - @Nullable - public IMarker getIssueForNode(@NonNull UiViewElementNode node) { - if (mNodeMap != null) { - return mNodeMap.get(node.getXmlNode()); - } - - return null; - } - - /** - * Returns a collection of nodes that have one or more lint warnings - * associated with them (retrievable via - * {@link #getIssueForNode(UiViewElementNode)}) - * - * @return a collection of nodes, which should <b>not</b> be modified by the - * caller - */ - @Nullable - public Collection<Node> getIssueNodes() { - if (mNodeMap != null) { - return mNodeMap.keySet(); - } - - return null; - } - - // ----- Extends LintClient ----- - - @Override - public void log(@NonNull Severity severity, @Nullable Throwable exception, - @Nullable String format, @Nullable Object... args) { - if (exception == null) { - AdtPlugin.log(IStatus.WARNING, format, args); - } else { - AdtPlugin.log(exception, format, args); - } - } - - @Override - public XmlParser getXmlParser() { - return new XmlParser() { - @Override - public Document parseXml(@NonNull XmlContext context) { - // Map File to IFile - IFile file = AdtUtils.fileToIFile(context.file); - if (file == null || !file.exists()) { - String path = context.file.getPath(); - AdtPlugin.log(IStatus.ERROR, "Can't find file %1$s in workspace", path); - return null; - } - - IStructuredModel model = null; - try { - IModelManager modelManager = StructuredModelManager.getModelManager(); - if (modelManager == null) { - // This can happen if incremental lint is running right as Eclipse is - // shutting down - return null; - } - model = modelManager.getModelForRead(file); - if (model instanceof IDOMModel) { - context.setProperty(MODEL_PROPERTY, model); - IDOMModel domModel = (IDOMModel) model; - return domModel.getDocument(); - } - } catch (IOException e) { - AdtPlugin.log(e, "Cannot read XML file"); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - return null; - } - - @Override - public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node) { - IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); - return new LazyLocation(context.file, model.getStructuredDocument(), - (IndexedRegion) node); - } - - @Override - public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node, - int start, int end) { - IndexedRegion region = (IndexedRegion) node; - int nodeStart = region.getStartOffset(); - - IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); - // Get line number - LazyLocation location = new LazyLocation(context.file, - model.getStructuredDocument(), region); - int line = location.getStart().getLine(); - - Position startPos = new DefaultPosition(line, -1, nodeStart + start); - Position endPos = new DefaultPosition(line, -1, nodeStart + end); - return Location.create(context.file, startPos, endPos); - } - - @Override - public int getNodeStartOffset(@NonNull XmlContext context, @NonNull Node node) { - IndexedRegion region = (IndexedRegion) node; - return region.getStartOffset(); - } - - @Override - public int getNodeEndOffset(@NonNull XmlContext context, @NonNull Node node) { - IndexedRegion region = (IndexedRegion) node; - return region.getEndOffset(); - } - - @Override - public @NonNull Handle createLocationHandle(final @NonNull XmlContext context, - final @NonNull Node node) { - IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); - return new LazyLocation(context.file, model.getStructuredDocument(), - (IndexedRegion) node); - } - - @Override - public void dispose(@NonNull XmlContext context, @NonNull Document document) { - IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); - assert model != null : context.file; - if (model != null) { - model.releaseFromRead(); - } - } - - @Override - @NonNull - public Location getNameLocation(@NonNull XmlContext context, @NonNull Node node) { - return getLocation(context, node); - } - - @Override - @NonNull - public Location getValueLocation(@NonNull XmlContext context, @NonNull Attr node) { - return getLocation(context, node); - } - - }; - } - - @Override - public JavaParser getJavaParser(@Nullable Project project) { - if (mJavaParser == null) { - mJavaParser = new EclipseJavaParser(); - } - - return mJavaParser; - } - - // Cache for {@link getProject} - private IProject mLastEclipseProject; - private Project mLastLintProject; - - private IProject getProject(Project project) { - if (project == mLastLintProject) { - return mLastEclipseProject; - } - - mLastLintProject = project; - mLastEclipseProject = null; - - if (mResources != null) { - if (mResources.size() == 1) { - IProject p = mResources.get(0).getProject(); - mLastEclipseProject = p; - return p; - } - - IProject last = null; - for (IResource resource : mResources) { - IProject p = resource.getProject(); - if (p != last) { - if (project.getDir().equals(AdtUtils.getAbsolutePath(p).toFile())) { - mLastEclipseProject = p; - return p; - } - last = p; - } - } - } - - return null; - } - - @Override - @NonNull - public String getProjectName(@NonNull Project project) { - // Initialize the lint project's name to the name of the Eclipse project, - // which might differ from the directory name - IProject eclipseProject = getProject(project); - if (eclipseProject != null) { - return eclipseProject.getName(); - } - - return super.getProjectName(project); - } - - @NonNull - @Override - public Configuration getConfiguration(@NonNull Project project, @Nullable LintDriver driver) { - return getConfigurationFor(project); - } - - /** - * Same as {@link #getConfiguration(Project)}, but {@code project} can be - * null in which case the global configuration is returned. - * - * @param project the project to look up - * @return a corresponding configuration - */ - @NonNull - public Configuration getConfigurationFor(@Nullable Project project) { - if (project != null) { - IProject eclipseProject = getProject(project); - if (eclipseProject != null) { - return ProjectLintConfiguration.get(this, eclipseProject, mFatalOnly); - } - } - - return GlobalLintConfiguration.get(); - } - @Override - public void report(@NonNull Context context, @NonNull Issue issue, @NonNull Severity s, - @Nullable Location location, - @NonNull String message, @NonNull TextFormat format) { - message = format.toText(message); - int severity = getMarkerSeverity(s); - IMarker marker = null; - if (location != null) { - Position startPosition = location.getStart(); - if (startPosition == null) { - if (location.getFile() != null) { - IResource resource = AdtUtils.fileToResource(location.getFile()); - if (resource != null && resource.isAccessible()) { - marker = BaseProjectHelper.markResource(resource, MARKER_LINT, - message, 0, severity); - } - } - } else { - Position endPosition = location.getEnd(); - int line = startPosition.getLine() + 1; // Marker API is 1-based - IFile file = AdtUtils.fileToIFile(location.getFile()); - if (file != null && file.isAccessible()) { - Pair<Integer, Integer> r = getRange(file, mDocument, - startPosition, endPosition); - int startOffset = r.getFirst(); - int endOffset = r.getSecond(); - marker = BaseProjectHelper.markResource(file, MARKER_LINT, - message, line, startOffset, endOffset, severity); - } - } - } - - if (marker == null) { - marker = BaseProjectHelper.markResource(mResources.get(0), MARKER_LINT, - message, 0, severity); - } - - if (marker != null) { - // Store marker id such that we can recognize it from the suppress quickfix - try { - marker.setAttribute(MARKER_CHECKID_PROPERTY, issue.getId()); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - - if (s == Severity.FATAL) { - mWasFatal = true; - } - - if (mCollectNodes && location != null && marker != null) { - if (location instanceof LazyLocation) { - LazyLocation l = (LazyLocation) location; - IndexedRegion region = l.mRegion; - if (region instanceof Node) { - Node node = (Node) region; - if (node instanceof Attr) { - node = ((Attr) node).getOwnerElement(); - } - if (mNodeMap == null) { - mNodeMap = new WeakHashMap<Node, IMarker>(); - } - IMarker prev = mNodeMap.get(node); - if (prev != null) { - // Only replace the node if this node has higher priority - int prevSeverity = prev.getAttribute(IMarker.SEVERITY, 0); - if (prevSeverity < severity) { - mNodeMap.put(node, marker); - } - } else { - mNodeMap.put(node, marker); - } - } - } - } - } - - @Override - @Nullable - public File findResource(@NonNull String relativePath) { - // Look within the $ANDROID_SDK - String sdkFolder = AdtPrefs.getPrefs().getOsSdkFolder(); - if (sdkFolder != null) { - File file = new File(sdkFolder, relativePath); - if (file.exists()) { - return file; - } - } - - return null; - } - - /** - * Clears any lint markers from the given resource (project, folder or file) - * - * @param resource the resource to remove markers from - */ - public static void clearMarkers(@NonNull IResource resource) { - clearMarkers(Collections.singletonList(resource)); - } - - /** Clears any lint markers from the given list of resource (project, folder or file) */ - static void clearMarkers(List<? extends IResource> resources) { - for (IResource resource : resources) { - try { - if (resource.isAccessible()) { - resource.deleteMarkers(MARKER_LINT, false, IResource.DEPTH_INFINITE); - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - - IEditorPart activeEditor = AdtUtils.getActiveEditor(); - LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(activeEditor); - if (delegate != null) { - delegate.getGraphicalEditor().getLayoutActionBar().updateErrorIndicator(); - } - } - - /** - * Removes all markers of the given id from the given resource. - * - * @param resource the resource to remove markers from (file or project, or - * null for all open projects) - * @param id the id for the issue whose markers should be deleted - */ - public static void removeMarkers(IResource resource, String id) { - if (resource == null) { - IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(null); - for (IJavaProject project : androidProjects) { - IProject p = project.getProject(); - if (p != null) { - // Recurse, but with a different parameter so it will not continue recursing - removeMarkers(p, id); - } - } - return; - } - IMarker[] markers = getMarkers(resource); - for (IMarker marker : markers) { - if (id.equals(getId(marker))) { - try { - marker.delete(); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - } - } - - /** - * Returns the lint marker for the given resource (which may be a project, folder or file) - * - * @param resource the resource to be checked, typically a source file - * @return an array of markers, possibly empty but never null - */ - public static IMarker[] getMarkers(IResource resource) { - try { - if (resource.isAccessible()) { - return resource.findMarkers(MARKER_LINT, false, IResource.DEPTH_INFINITE); - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - - return new IMarker[0]; - } - - private static int getMarkerSeverity(Severity severity) { - switch (severity) { - case INFORMATIONAL: - return IMarker.SEVERITY_INFO; - case WARNING: - return IMarker.SEVERITY_WARNING; - case FATAL: - case ERROR: - default: - return IMarker.SEVERITY_ERROR; - } - } - - private static Pair<Integer, Integer> getRange(IFile file, IDocument doc, - Position startPosition, Position endPosition) { - int startOffset = startPosition.getOffset(); - int endOffset = endPosition != null ? endPosition.getOffset() : -1; - if (endOffset != -1) { - // Attribute ranges often include trailing whitespace; trim this up - if (doc == null) { - IDocumentProvider provider = new TextFileDocumentProvider(); - try { - provider.connect(file); - doc = provider.getDocument(file); - if (doc != null) { - return adjustOffsets(doc, startOffset, endOffset); - } - } catch (Exception e) { - AdtPlugin.log(e, "Can't find range information for %1$s", file.getName()); - } finally { - provider.disconnect(file); - } - } else { - return adjustOffsets(doc, startOffset, endOffset); - } - } - - return Pair.of(startOffset, startOffset); - } - - /** - * Trim off any trailing space on the given offset range in the given - * document, and don't span multiple lines on ranges since it makes (for - * example) the XML editor just glow with yellow underlines for all the - * attributes etc. Highlighting just the element beginning gets the point - * across. It also makes it more obvious where there are warnings on both - * the overall element and on individual attributes since without this the - * warnings on attributes would just overlap with the whole-element - * highlighting. - */ - private static Pair<Integer, Integer> adjustOffsets(IDocument doc, int startOffset, - int endOffset) { - int originalStart = startOffset; - int originalEnd = endOffset; - - if (doc != null) { - while (endOffset > startOffset && endOffset < doc.getLength()) { - try { - if (!Character.isWhitespace(doc.getChar(endOffset - 1))) { - break; - } else { - endOffset--; - } - } catch (BadLocationException e) { - // Pass - we've already validated offset range above - break; - } - } - - // Also don't span lines - int lineEnd = startOffset; - while (lineEnd < endOffset) { - try { - char c = doc.getChar(lineEnd); - if (c == '\n' || c == '\r') { - endOffset = lineEnd; - if (endOffset > 0 && doc.getChar(endOffset - 1) == '\r') { - endOffset--; - } - break; - } - } catch (BadLocationException e) { - // Pass - we've already validated offset range above - break; - } - lineEnd++; - } - } - - if (startOffset >= endOffset) { - // Selecting nothing (for example, for the mangled CRLF delimiter issue selecting - // just the newline) - // In that case, use the real range - return Pair.of(originalStart, originalEnd); - } - - return Pair.of(startOffset, endOffset); - } - - /** - * Returns true if a fatal error was encountered - * - * @return true if a fatal error was encountered - */ - public boolean hasFatalErrors() { - return mWasFatal; - } - - /** - * Describe the issue for the given marker - * - * @param marker the marker to look up - * @return a full description of the corresponding issue, never null - */ - public static String describe(IMarker marker) { - IssueRegistry registry = getRegistry(); - String markerId = getId(marker); - Issue issue = registry.getIssue(markerId); - if (issue == null) { - return ""; - } - - String summary = issue.getBriefDescription(TextFormat.TEXT); - String explanation = issue.getExplanation(TextFormat.TEXT); - - StringBuilder sb = new StringBuilder(summary.length() + explanation.length() + 20); - try { - sb.append((String) marker.getAttribute(IMarker.MESSAGE)); - sb.append('\n').append('\n'); - } catch (CoreException e) { - } - sb.append("Issue: "); - sb.append(summary); - sb.append('\n'); - sb.append("Id: "); - sb.append(issue.getId()); - sb.append('\n').append('\n'); - sb.append(explanation); - - if (issue.getMoreInfo() != null) { - sb.append('\n').append('\n'); - sb.append(issue.getMoreInfo()); - } - - return sb.toString(); - } - - /** - * Returns the id for the given marker - * - * @param marker the marker to look up - * @return the corresponding issue id, or null - */ - public static String getId(IMarker marker) { - try { - return (String) marker.getAttribute(MARKER_CHECKID_PROPERTY); - } catch (CoreException e) { - return null; - } - } - - /** - * Shows the given marker in the editor - * - * @param marker the marker to be shown - */ - public static void showMarker(IMarker marker) { - IRegion region = null; - try { - int start = marker.getAttribute(IMarker.CHAR_START, -1); - int end = marker.getAttribute(IMarker.CHAR_END, -1); - if (start >= 0 && end >= 0) { - region = new org.eclipse.jface.text.Region(start, end - start); - } - - IResource resource = marker.getResource(); - if (resource instanceof IFile) { - IEditorPart editor = - AdtPlugin.openFile((IFile) resource, region, true /* showEditorTab */); - if (editor != null) { - IDE.gotoMarker(editor, marker); - } - } - } catch (PartInitException ex) { - AdtPlugin.log(ex, null); - } - } - - /** - * Show a dialog with errors for the given file - * - * @param shell the parent shell to attach the dialog to - * @param file the file to show the errors for - * @param editor the editor for the file, if known - */ - public static void showErrors( - @NonNull Shell shell, - @NonNull IFile file, - @Nullable IEditorPart editor) { - LintListDialog dialog = new LintListDialog(shell, file, editor); - dialog.open(); - } - - @Override - public @NonNull String readFile(@NonNull File f) { - // Map File to IFile - IFile file = AdtUtils.fileToIFile(f); - if (file == null || !file.exists()) { - String path = f.getPath(); - AdtPlugin.log(IStatus.ERROR, "Can't find file %1$s in workspace", path); - return readPlainFile(f); - } - - if (SdkUtils.endsWithIgnoreCase(file.getName(), DOT_XML)) { - IStructuredModel model = null; - try { - IModelManager modelManager = StructuredModelManager.getModelManager(); - model = modelManager.getModelForRead(file); - return model.getStructuredDocument().get(); - } catch (IOException e) { - AdtPlugin.log(e, "Cannot read XML file"); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } finally { - if (model != null) { - // TODO: This may be too early... - model.releaseFromRead(); - } - } - } - - return readPlainFile(f); - } - - private String readPlainFile(File file) { - try { - return LintUtils.getEncodedString(this, file); - } catch (IOException e) { - return ""; //$NON-NLS-1$ - } - } - - private Map<Project, ClassPathInfo> mProjectInfo; - - @Override - @NonNull - protected ClassPathInfo getClassPath(@NonNull Project project) { - ClassPathInfo info; - if (mProjectInfo == null) { - mProjectInfo = Maps.newHashMap(); - info = null; - } else { - info = mProjectInfo.get(project); - } - - if (info == null) { - List<File> sources = null; - List<File> classes = null; - List<File> libraries = null; - - IProject p = getProject(project); - if (p != null) { - try { - IJavaProject javaProject = BaseProjectHelper.getJavaProject(p); - - // Output path - File file = workspacePathToFile(javaProject.getOutputLocation()); - classes = Collections.singletonList(file); - - // Source path - IClasspathEntry[] entries = javaProject.getRawClasspath(); - sources = new ArrayList<File>(entries.length); - libraries = new ArrayList<File>(entries.length); - for (int i = 0; i < entries.length; i++) { - IClasspathEntry entry = entries[i]; - int kind = entry.getEntryKind(); - - if (kind == IClasspathEntry.CPE_VARIABLE) { - entry = JavaCore.getResolvedClasspathEntry(entry); - if (entry == null) { - // It's possible that the variable is no longer valid; ignore - continue; - } - kind = entry.getEntryKind(); - } - - if (kind == IClasspathEntry.CPE_SOURCE) { - sources.add(workspacePathToFile(entry.getPath())); - } else if (kind == IClasspathEntry.CPE_LIBRARY) { - libraries.add(entry.getPath().toFile()); - } - // Note that we ignore IClasspathEntry.CPE_CONTAINER: - // Normal Android Eclipse projects supply both - // AdtConstants.CONTAINER_FRAMEWORK - // and - // AdtConstants.CONTAINER_LIBRARIES - // here. We ignore the framework classes for obvious reasons, - // but we also ignore the library container because lint will - // process the libraries differently. When Eclipse builds a - // project, it gets the .jar output of the library projects - // from this container, which means it doesn't have to process - // the library sources. Lint on the other hand wants to process - // the source code, so instead it actually looks at the - // project.properties file to find the libraries, and then it - // iterates over all the library projects in turn and analyzes - // those separately (but passing the main project for context, - // such that the including project's manifest declarations - // are used for data like minSdkVersion level). - // - // Note that this container will also contain *other* - // libraries (Java libraries, not library projects) that we - // *should* include. However, we can't distinguish these - // class path entries from the library project jars, - // so instead of looking at these, we simply listFiles() in - // the libs/ folder after processing the classpath info - } - - // Add in libraries - File libs = new File(project.getDir(), FD_NATIVE_LIBS); - if (libs.isDirectory()) { - File[] jars = libs.listFiles(); - if (jars != null) { - for (File jar : jars) { - if (SdkUtils.endsWith(jar.getPath(), DOT_JAR)) { - libraries.add(jar); - } - } - } - } - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - - if (sources == null) { - sources = super.getClassPath(project).getSourceFolders(); - } - if (classes == null) { - classes = super.getClassPath(project).getClassFolders(); - } - if (libraries == null) { - libraries = super.getClassPath(project).getLibraries(); - } - - - // No test folders in Eclipse: - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=224708 - List<File> tests = Collections.emptyList(); - - info = new ClassPathInfo(sources, classes, libraries, tests); - mProjectInfo.put(project, info); - } - - return info; - } - - /** - * Returns the registry of issues to check from within Eclipse. - * - * @return the issue registry to use to access detectors and issues - */ - public static IssueRegistry getRegistry() { - return new EclipseLintIssueRegistry(); - } - - @Override - public @NonNull Class<? extends Detector> replaceDetector( - @NonNull Class<? extends Detector> detectorClass) { - return detectorClass; - } - - @Override - @NonNull - public IAndroidTarget[] getTargets() { - Sdk sdk = Sdk.getCurrent(); - if (sdk != null) { - return sdk.getTargets(); - } else { - return new IAndroidTarget[0]; - } - } - - private boolean mSearchForSuperClasses; - - /** - * Sets whether this client should search for super types on its own. This - * is typically not needed when doing a full lint run (because lint will - * look at all classes and libraries), but is useful during incremental - * analysis when lint is only looking at a subset of classes. In that case, - * we want to use Eclipse's data structures for super classes. - * - * @param search whether to use a custom Eclipse search for super class - * names - */ - public void setSearchForSuperClasses(boolean search) { - mSearchForSuperClasses = search; - } - - /** - * Whether this lint client is searching for super types. See - * {@link #setSearchForSuperClasses(boolean)} for details. - * - * @return whether the client will search for super types - */ - public boolean getSearchForSuperClasses() { - return mSearchForSuperClasses; - } - - @Override - @Nullable - public String getSuperClass(@NonNull Project project, @NonNull String name) { - if (!mSearchForSuperClasses) { - // Super type search using the Eclipse index is potentially slow, so - // only do this when necessary - return null; - } - - IProject eclipseProject = getProject(project); - if (eclipseProject == null) { - return null; - } - - try { - IJavaProject javaProject = BaseProjectHelper.getJavaProject(eclipseProject); - if (javaProject == null) { - return null; - } - - String typeFqcn = ClassContext.getFqcn(name); - IType type = javaProject.findType(typeFqcn); - if (type != null) { - ITypeHierarchy hierarchy = type.newSupertypeHierarchy(new NullProgressMonitor()); - IType superType = hierarchy.getSuperclass(type); - if (superType != null) { - String key = superType.getKey(); - if (!key.isEmpty() - && key.charAt(0) == 'L' - && key.charAt(key.length() - 1) == ';') { - return key.substring(1, key.length() - 1); - } else { - String fqcn = superType.getFullyQualifiedName(); - return ClassContext.getInternalName(fqcn); - } - } - } - } catch (JavaModelException e) { - log(Severity.INFORMATIONAL, e, null); - } catch (CoreException e) { - log(Severity.INFORMATIONAL, e, null); - } - - return null; - } - - @Override - @Nullable - public Boolean isSubclassOf( - @NonNull Project project, - @NonNull String name, @NonNull - String superClassName) { - if (!mSearchForSuperClasses) { - // Super type search using the Eclipse index is potentially slow, so - // only do this when necessary - return null; - } - - IProject eclipseProject = getProject(project); - if (eclipseProject == null) { - return null; - } - - try { - IJavaProject javaProject = BaseProjectHelper.getJavaProject(eclipseProject); - if (javaProject == null) { - return null; - } - - String typeFqcn = ClassContext.getFqcn(name); - IType type = javaProject.findType(typeFqcn); - if (type != null) { - ITypeHierarchy hierarchy = type.newSupertypeHierarchy(new NullProgressMonitor()); - IType[] allSupertypes = hierarchy.getAllSuperclasses(type); - if (allSupertypes != null) { - String target = 'L' + superClassName + ';'; - for (IType superType : allSupertypes) { - if (target.equals(superType.getKey())) { - return Boolean.TRUE; - } - } - return Boolean.FALSE; - } - } - } catch (JavaModelException e) { - log(Severity.INFORMATIONAL, e, null); - } catch (CoreException e) { - log(Severity.INFORMATIONAL, e, null); - } - - return null; - } - - private static class LazyLocation extends Location implements Location.Handle { - private final IStructuredDocument mDocument; - private final IndexedRegion mRegion; - private Position mStart; - private Position mEnd; - - public LazyLocation(File file, IStructuredDocument document, IndexedRegion region) { - super(file, null /*start*/, null /*end*/); - mDocument = document; - mRegion = region; - } - - @Override - public Position getStart() { - if (mStart == null) { - int line = -1; - int column = -1; - int offset = mRegion.getStartOffset(); - - if (mRegion instanceof org.w3c.dom.Text && mDocument != null) { - // For text nodes, skip whitespace prefix, if any - for (int i = offset; - i < mRegion.getEndOffset() && i < mDocument.getLength(); i++) { - try { - char c = mDocument.getChar(i); - if (!Character.isWhitespace(c)) { - offset = i; - break; - } - } catch (BadLocationException e) { - break; - } - } - } - - if (mDocument != null && offset < mDocument.getLength()) { - line = mDocument.getLineOfOffset(offset); - column = -1; - try { - int lineOffset = mDocument.getLineOffset(line); - column = offset - lineOffset; - } catch (BadLocationException e) { - AdtPlugin.log(e, null); - } - } - - mStart = new DefaultPosition(line, column, offset); - } - - return mStart; - } - - @Override - public Position getEnd() { - if (mEnd == null) { - mEnd = new DefaultPosition(-1, -1, mRegion.getEndOffset()); - } - - return mEnd; - } - - @Override - public @NonNull Location resolve() { - return this; - } - } - - private static class EclipseJavaParser extends JavaParser { - private static final boolean USE_ECLIPSE_PARSER = true; - private final Parser mParser; - - EclipseJavaParser() { - if (USE_ECLIPSE_PARSER) { - CompilerOptions options = new CompilerOptions(); - // Always using JDK 7 rather than basing it on project metadata since we - // don't do compilation error validation in lint (we leave that to the IDE's - // error parser or the command line build's compilation step); we want an - // AST that is as tolerant as possible. - options.complianceLevel = ClassFileConstants.JDK1_7; - options.sourceLevel = ClassFileConstants.JDK1_7; - options.targetJDK = ClassFileConstants.JDK1_7; - options.parseLiteralExpressionsAsConstants = true; - ProblemReporter problemReporter = new ProblemReporter( - DefaultErrorHandlingPolicies.exitOnFirstError(), - options, - new DefaultProblemFactory()); - mParser = new Parser(problemReporter, options.parseLiteralExpressionsAsConstants); - mParser.javadocParser.checkDocComment = false; - } else { - mParser = null; - } - } - - @Override - public void prepareJavaParse(@NonNull List<JavaContext> contexts) { - // TODO: Use batch compiler from lint-cli.jar - } - - @Override - public lombok.ast.Node parseJava(@NonNull JavaContext context) { - if (USE_ECLIPSE_PARSER) { - // Use Eclipse's compiler - EcjTreeConverter converter = new EcjTreeConverter(); - String code = context.getContents(); - - CompilationUnit sourceUnit = new CompilationUnit(code.toCharArray(), - context.file.getName(), "UTF-8"); //$NON-NLS-1$ - CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0); - CompilationUnitDeclaration unit = null; - try { - unit = mParser.parse(sourceUnit, compilationResult); - } catch (AbortCompilation e) { - // No need to report Java parsing errors while running in Eclipse. - // Eclipse itself will already provide problem markers for these files, - // so all this achieves is creating "multiple annotations on this line" - // tooltips instead. - return null; - } - if (unit == null) { - return null; - } - - try { - converter.visit(code, unit); - List<? extends lombok.ast.Node> nodes = converter.getAll(); - - // There could be more than one node when there are errors; pick out the - // compilation unit node - for (lombok.ast.Node node : nodes) { - if (node instanceof lombok.ast.CompilationUnit) { - return node; - } - } - - return null; - } catch (Throwable t) { - AdtPlugin.log(t, "Failed converting ECJ parse tree to Lombok for file %1$s", - context.file.getPath()); - return null; - } - } else { - // Use Lombok for now - Source source = new Source(context.getContents(), context.file.getName()); - List<lombok.ast.Node> nodes = source.getNodes(); - - // Don't analyze files containing errors - List<ParseProblem> problems = source.getProblems(); - if (problems != null && problems.size() > 0) { - /* Silently ignore the errors. There are still some bugs in Lombok/Parboiled - * (triggered if you run lint on the AOSP framework directory for example), - * and having these show up as fatal errors when it's really a tool bug - * is bad. To make matters worse, the error messages aren't clear: - * http://code.google.com/p/projectlombok/issues/detail?id=313 - for (ParseProblem problem : problems) { - lombok.ast.Position position = problem.getPosition(); - Location location = Location.create(context.file, - context.getContents(), position.getStart(), position.getEnd()); - String message = problem.getMessage(); - context.report( - IssueRegistry.PARSER_ERROR, location, - message, - null); - - } - */ - return null; - } - - // There could be more than one node when there are errors; pick out the - // compilation unit node - for (lombok.ast.Node node : nodes) { - if (node instanceof lombok.ast.CompilationUnit) { - return node; - } - } - return null; - } - } - - @Override - public @NonNull Location getLocation(@NonNull JavaContext context, - @NonNull lombok.ast.Node node) { - lombok.ast.Position position = node.getPosition(); - return Location.create(context.file, context.getContents(), - position.getStart(), position.getEnd()); - } - - @Override - public @NonNull Handle createLocationHandle(@NonNull JavaContext context, - @NonNull lombok.ast.Node node) { - return new LocationHandle(context.file, node); - } - - @Override - public void dispose(@NonNull JavaContext context, - @NonNull lombok.ast.Node compilationUnit) { - } - - @Override - @Nullable - public ResolvedNode resolve(@NonNull JavaContext context, - @NonNull lombok.ast.Node node) { - return null; - } - - @Override - @Nullable - public TypeDescriptor getType(@NonNull JavaContext context, - @NonNull lombok.ast.Node node) { - return null; - } - - /* Handle for creating positions cheaply and returning full fledged locations later */ - private class LocationHandle implements Handle { - private File mFile; - private lombok.ast.Node mNode; - private Object mClientData; - - public LocationHandle(File file, lombok.ast.Node node) { - mFile = file; - mNode = node; - } - - @Override - public @NonNull Location resolve() { - lombok.ast.Position pos = mNode.getPosition(); - return Location.create(mFile, null /*contents*/, pos.getStart(), pos.getEnd()); - } - - @Override - public void setClientData(@Nullable Object clientData) { - mClientData = clientData; - } - - @Override - @Nullable - public Object getClientData() { - return mClientData; - } - } - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintIssueRegistry.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintIssueRegistry.java deleted file mode 100644 index 3abbdeb84..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintIssueRegistry.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2014 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.tools.lint.checks.*; -import com.android.tools.lint.detector.api.Issue; - -import java.util.ArrayList; -import java.util.List; - -public class EclipseLintIssueRegistry extends BuiltinIssueRegistry { - private static List<Issue> sFilteredIssues; - - public EclipseLintIssueRegistry() { - } - - @NonNull - @Override - public List<Issue> getIssues() { - if (sFilteredIssues == null) { - // Remove issues that do not work properly in Eclipse - List<Issue> sIssues = super.getIssues(); - List<Issue> result = new ArrayList<Issue>(sIssues.size()); - for (Issue issue : sIssues) { - if (issue == MissingClassDetector.INSTANTIATABLE) { - // Apparently violated by - // android.support.v7.internal.widget.ActionBarView.HomeView - // See issue 72760 - continue; - } else if (issue == DuplicateIdDetector.WITHIN_LAYOUT) { - // Apparently violated by - // sdk/extras/android/support/v7/appcompat/abc_activity_chooser_view_include.xml - // See issue 72760 - continue; - } else if (issue == AppCompatResourceDetector.ISSUE - || issue == AppCompatCallDetector.ISSUE) { - // Apparently has some false positives in Eclipse; see issue - // 72824 - continue; - } else if (issue.getImplementation().getDetectorClass() == RtlDetector.class) { - // False positives in Eclipse; see issue 78780 - continue; - } - result.add(issue); - } - sFilteredIssues = result; - } - - return sFilteredIssues; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintRunner.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintRunner.java deleted file mode 100644 index 43cd48d1b..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintRunner.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.tools.lint.client.api.IssueRegistry; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.text.IDocument; -import org.eclipse.swt.widgets.Shell; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; - -/** - * Eclipse implementation for running lint on workspace files and projects. - */ -public class EclipseLintRunner { - static final String MARKER_CHECKID_PROPERTY = "checkid"; //$NON-NLS-1$ - - /** - * Runs lint and updates the markers, and waits for the result. Returns - * true if fatal errors were found. - * - * @param resources the resources (project, folder or file) to be analyzed - * @param source if checking a single source file, the source file - * @param doc the associated document, if known, or null - * @param fatalOnly if true, only report fatal issues (severity=error) - * @return true if any fatal errors were encountered. - */ - private static boolean runLint( - @NonNull List<? extends IResource> resources, - @Nullable IResource source, - @Nullable IDocument doc, - boolean fatalOnly) { - resources = addLibraries(resources); - LintJob job = (LintJob) startLint(resources, source, doc, fatalOnly, - false /*show*/); - try { - job.join(); - boolean fatal = job.isFatal(); - - if (fatal) { - LintViewPart.show(resources); - } - - return fatal; - } catch (InterruptedException e) { - AdtPlugin.log(e, null); - } - - return false; - } - - /** - * Runs lint and updates the markers. Does not wait for the job to finish - - * just returns immediately. - * - * @param resources the resources (project, folder or file) to be analyzed - * @param source if checking a single source file, the source file. When - * single checking an XML file, this is typically the same as the - * file passed in the list in the first parameter, but when - * checking the .class files of a Java file for example, the - * .class file and all the inner classes of the Java file are - * passed in the first parameter, and the corresponding .java - * source file is passed here. - * @param doc the associated document, if known, or null - * @param fatalOnly if true, only report fatal issues (severity=error) - * @param show if true, show the results in a {@link LintViewPart} - * @return the job running lint in the background. - */ - public static Job startLint( - @NonNull List<? extends IResource> resources, - @Nullable IResource source, - @Nullable IDocument doc, - boolean fatalOnly, - boolean show) { - IssueRegistry registry = EclipseLintClient.getRegistry(); - EclipseLintClient client = new EclipseLintClient(registry, resources, doc, fatalOnly); - return startLint(client, resources, source, show); - } - - /** - * Runs lint and updates the markers. Does not wait for the job to finish - - * just returns immediately. - * - * @param client the lint client receiving issue reports etc - * @param resources the resources (project, folder or file) to be analyzed - * @param source if checking a single source file, the source file. When - * single checking an XML file, this is typically the same as the - * file passed in the list in the first parameter, but when - * checking the .class files of a Java file for example, the - * .class file and all the inner classes of the Java file are - * passed in the first parameter, and the corresponding .java - * source file is passed here. - * @param show if true, show the results in a {@link LintViewPart} - * @return the job running lint in the background. - */ - public static Job startLint( - @NonNull EclipseLintClient client, - @NonNull List<? extends IResource> resources, - @Nullable IResource source, - boolean show) { - if (resources != null && !resources.isEmpty()) { - if (!AdtPrefs.getPrefs().getSkipLibrariesFromLint()) { - resources = addLibraries(resources); - } - - cancelCurrentJobs(false); - - LintJob job = new LintJob(client, resources, source); - job.schedule(); - - if (show) { - // Show lint view where the results are listed - LintViewPart.show(resources); - } - return job; - } - - return null; - } - - /** - * Run Lint for an Export APK action. If it succeeds (no fatal errors) - * returns true, and if it fails it will display an error message and return - * false. - * - * @param shell the parent shell to show error messages in - * @param project the project to run lint on - * @return true if the lint run succeeded with no fatal errors - */ - public static boolean runLintOnExport(Shell shell, IProject project) { - if (AdtPrefs.getPrefs().isLintOnExport()) { - boolean fatal = EclipseLintRunner.runLint(Collections.singletonList(project), - null, null, true /*fatalOnly*/); - if (fatal) { - MessageDialog.openWarning(shell, - "Export Aborted", - "Export aborted because fatal lint errors were found. These " + - "are listed in the Lint View. Either fix these before " + - "running Export again, or turn off \"Run full error check " + - "when exporting app\" in the Android > Lint Error Checking " + - "preference page."); - return false; - } - } - - return true; - } - - /** Cancels the current lint jobs, if any, and optionally waits for them to finish */ - static void cancelCurrentJobs(boolean wait) { - // Cancel any current running jobs first - Job[] currentJobs = LintJob.getCurrentJobs(); - for (Job job : currentJobs) { - job.cancel(); - } - - if (wait) { - for (Job job : currentJobs) { - try { - job.join(); - } catch (InterruptedException e) { - AdtPlugin.log(e, null); - } - } - } - } - - /** If the resource list contains projects, add in any library projects as well */ - private static List<? extends IResource> addLibraries(List<? extends IResource> resources) { - if (resources != null && !resources.isEmpty()) { - boolean haveProjects = false; - for (IResource resource : resources) { - if (resource instanceof IProject) { - haveProjects = true; - break; - } - } - - if (haveProjects) { - List<IResource> result = new ArrayList<IResource>(); - Map<IProject, IProject> allProjects = new IdentityHashMap<IProject, IProject>(); - List<IProject> projects = new ArrayList<IProject>(); - for (IResource resource : resources) { - if (resource instanceof IProject) { - IProject project = (IProject) resource; - allProjects.put(project, project); - projects.add(project); - } else { - result.add(resource); - } - } - for (IProject project : projects) { - ProjectState state = Sdk.getProjectState(project); - if (state != null) { - for (IProject library : state.getFullLibraryProjects()) { - allProjects.put(library, library); - } - } - } - for (IProject project : allProjects.keySet()) { - result.add(project); - } - - return result; - } - } - - return resources; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ExtractStringFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ExtractStringFix.java deleted file mode 100644 index 7eafd4364..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ExtractStringFix.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; -import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring; -import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextSelection; -import org.eclipse.jface.text.TextSelection; -import org.eclipse.ltk.ui.refactoring.RefactoringWizard; -import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Node; - -/** - * Fix for extracting strings. - * <p> - * TODO: Look for existing string values, and if it matches one of the - * existing Strings offer to just replace it with the given string! - */ -@SuppressWarnings("restriction") // DOM model -final class ExtractStringFix extends DocumentFix { - private ExtractStringFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return true; - } - - @Override - public boolean isCancelable() { - return true; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - IEditorPart editorPart = AdtUtils.getActiveEditor(); - if (editorPart instanceof AndroidXmlEditor) { - IFile file = (IFile) mMarker.getResource(); - ITextSelection selection = new TextSelection(start, end - start); - - ExtractStringRefactoring refactoring = - new ExtractStringRefactoring(file, editorPart, selection); - RefactoringWizard wizard = new ExtractStringWizard(refactoring, file.getProject()); - RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); - try { - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - op.run(window.getShell(), wizard.getDefaultPageTitle()); - } catch (InterruptedException e) { - } - } - } - - @Override - public String getDisplayString() { - return "Extract String"; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_OBJ_ADD); - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/GlobalLintConfiguration.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/GlobalLintConfiguration.java deleted file mode 100644 index 2f0261e7b..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/GlobalLintConfiguration.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.tools.lint.client.api.Configuration; -import com.android.tools.lint.client.api.IssueRegistry; -import com.android.tools.lint.detector.api.Context; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.Location; -import com.android.tools.lint.detector.api.Severity; - -import org.eclipse.jface.preference.IPreferenceStore; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** Global (non-project-specific) configuration for Lint in Eclipse */ -class GlobalLintConfiguration extends Configuration { - private static final GlobalLintConfiguration sInstance = new GlobalLintConfiguration(); - - private Map<Issue, Severity> mSeverities; - private boolean mBulkEditing; - - private GlobalLintConfiguration() { - } - - /** - * Obtain a reference to the singleton - * - * @return the singleton configuration - */ - @NonNull - public static GlobalLintConfiguration get() { - return sInstance; - } - - @Override - public Severity getSeverity(@NonNull Issue issue) { - if (mSeverities == null) { - IssueRegistry registry = EclipseLintClient.getRegistry(); - mSeverities = new HashMap<Issue, Severity>(); - IPreferenceStore store = getStore(); - String assignments = store.getString(AdtPrefs.PREFS_LINT_SEVERITIES); - if (assignments != null && assignments.length() > 0) { - for (String assignment : assignments.split(",")) { //$NON-NLS-1$ - String[] s = assignment.split("="); //$NON-NLS-1$ - if (s.length == 2) { - Issue d = registry.getIssue(s[0]); - if (d != null) { - Severity severity = Severity.valueOf(s[1]); - if (severity != null) { - mSeverities.put(d, severity); - } - } - } - } - } - } - - Severity severity = mSeverities.get(issue); - if (severity != null) { - return severity; - } - - if (!issue.isEnabledByDefault()) { - return Severity.IGNORE; - } - - return issue.getDefaultSeverity(); - } - - private IPreferenceStore getStore() { - IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); - return store; - } - - @Override - public void ignore(@NonNull Context context, @NonNull Issue issue, - @Nullable Location location, @NonNull String message) { - throw new UnsupportedOperationException( - "Can't ignore() in global configurations"); //$NON-NLS-1$ - } - - @Override - public void setSeverity(@NonNull Issue issue, @Nullable Severity severity) { - if (mSeverities == null) { - // Force initialization - getSeverity(issue); - } - - if (severity == null) { - mSeverities.remove(issue); - } else { - mSeverities.put(issue, severity); - } - - if (!mBulkEditing) { - setSeverities(mSeverities); - } - } - - /** - * Sets the custom severities for the given issues, in bulk. - * - * @param severities a map from detector to severity to use from now on - * @return true if something changed from the current settings - */ - private boolean setSeverities(Map<Issue, Severity> severities) { - mSeverities = severities; - - String value = ""; - if (severities.size() > 0) { - List<Issue> sortedKeys = new ArrayList<Issue>(severities.keySet()); - Collections.sort(sortedKeys); - - StringBuilder sb = new StringBuilder(severities.size() * 20); - for (Issue issue : sortedKeys) { - Severity severity = severities.get(issue); - if (severity != issue.getDefaultSeverity()) { - if (sb.length() > 0) { - sb.append(','); - } - sb.append(issue.getId()); - sb.append('='); - sb.append(severity.name()); - } - } - - value = sb.toString(); - } - - IPreferenceStore store = getStore(); - String previous = store.getString(AdtPrefs.PREFS_LINT_SEVERITIES); - boolean changed = !value.equals(previous); - if (changed) { - if (value.length() == 0) { - store.setToDefault(AdtPrefs.PREFS_LINT_SEVERITIES); - } else { - store.setValue(AdtPrefs.PREFS_LINT_SEVERITIES, value); - } - } - - return changed; - } - - @Override - public void startBulkEditing() { - mBulkEditing = true; - } - - @Override - public void finishBulkEditing() { - mBulkEditing = false; - setSeverities(mSeverities); - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/InputDensityDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/InputDensityDialog.java deleted file mode 100644 index d102225b2..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/InputDensityDialog.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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.resources.Density; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -import java.util.ArrayList; -import java.util.List; - -class InputDensityDialog extends Dialog { - private Combo mCombo; - /** - * Density value being chosen - static to keep most recently chosen value - * across repeated invocations - */ - private static int sDpi = Density.DEFAULT_DENSITY; - - InputDensityDialog(Shell parentShell) { - super(parentShell); - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite container = (Composite) super.createDialogArea(parent); - container.setLayout(new GridLayout(1, false)); - - Label lblWhatIsThe = new Label(container, SWT.WRAP); - lblWhatIsThe.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); - lblWhatIsThe.setText("What is the screen density the current px value works with?"); - - mCombo = new Combo(container, SWT.READ_ONLY); - GridData gdCombo = new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1); - gdCombo.widthHint = 200; - mCombo.setLayoutData(gdCombo); - int initialIndex = 0; - List<String> s = new ArrayList<String>(); - int index = 0; - for (Density density : Density.values()) { - if (density == Density.NODPI) { - continue; - } - if (density.getDpiValue() == sDpi) { - initialIndex = index; - } - s.add(getLabel(density)); - index++; - } - String[] items = s.toArray(new String[s.size()]); - mCombo.setItems(items); - mCombo.select(initialIndex); - - return container; - } - - private static String getLabel(Density density) { - return String.format("%1$s (%2$d)", density.getShortDisplayValue(), density.getDpiValue()); - } - - @Override - protected void createButtonsForButtonBar(Composite parent) { - createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); - createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); - } - - @Override - protected Point getInitialSize() { - return new Point(450, 150); - } - - @Override - public boolean close() { - String description = mCombo.getItem(mCombo.getSelectionIndex()); - - for (Density density : Density.values()) { - if (description.equals(getLabel(density))) { - sDpi = density.getDpiValue(); - break; - } - } - - return super.close(); - } - - @Override - protected void configureShell(Shell shell) { - super.configureShell(shell); - shell.setText("Choose Density"); - } - - int getDensity() { - return sDpi; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LinearLayoutWeightFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LinearLayoutWeightFix.java deleted file mode 100644 index af3fc74eb..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LinearLayoutWeightFix.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.ANDROID_URI; -import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT; -import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH; -import static com.android.SdkConstants.ATTR_ORIENTATION; -import static com.android.SdkConstants.VALUE_VERTICAL; -import static com.android.SdkConstants.VALUE_ZERO_DP; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -@SuppressWarnings("restriction") // DOM model -final class LinearLayoutWeightFix extends DocumentFix { - private LinearLayoutWeightFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - if (node instanceof Element && node.getParentNode() instanceof Element) { - Element element = (Element) node; - Element parent = (Element) node.getParentNode(); - String dimension; - if (VALUE_VERTICAL.equals(parent.getAttributeNS(ANDROID_URI, - ATTR_ORIENTATION))) { - dimension = ATTR_LAYOUT_HEIGHT; - } else { - dimension = ATTR_LAYOUT_WIDTH; - } - element.setAttributeNS(ANDROID_URI, dimension, VALUE_ZERO_DP); - } - } - - @Override - public String getDisplayString() { - return "Replace size attribute with 0dp"; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - // TODO: Need a better icon here - return sharedImages.getImage(ISharedImages.IMG_OBJ_ELEMENT); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintColumn.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintColumn.java deleted file mode 100644 index 297d94b79..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintColumn.java +++ /dev/null @@ -1,532 +0,0 @@ -/* - * 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.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils; -import com.android.tools.lint.detector.api.Issue; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.jface.viewers.StyledString; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; - -import java.io.File; -import java.util.Comparator; - -/** A column shown in the {@link LintList} */ -abstract class LintColumn implements Comparator<IMarker> { - protected final LintList mList; - - protected LintColumn(@NonNull LintList list) { - mList = list; - } - - /** @return true if this column should be shown by default */ - public boolean isVisibleByDefault() { - return true; - } - - /** @return true if this column's text should be left aligned */ - public boolean isLeftAligned() { - return true; - } - - /** - * @return the number of pixels that this column should show by default - */ - public int getPreferredWidth() { - return getPreferredCharWidth() * SwtUtils.getAverageCharWidth(mList.getDisplay(), - mList.getTree().getFont()); - } - - /** - * @return the number of characters that this column should show by default - */ - public int getPreferredCharWidth() { - return 15; - } - - /** - * @return the title of the column - */ - @NonNull - public abstract String getColumnHeaderText(); - - /** - * @return the image of the column, or null - */ - public Image getColumnHeaderImage() { - return null; - } - - /** - * @param marker the {@link IMarker} to get the value for - * @return the value of this column for the given marker - */ - public abstract String getValue(@NonNull IMarker marker); - - /** - * @param marker the {@link IMarker} to get the value for - * @return the styled value of this column for the given marker - */ - public StyledString getStyledValue(@NonNull IMarker marker) { - return null; - } - - /** - * @param marker the {@link IMarker} to get the image for - * @return The image for this particular column, or null - */ - @Nullable - public Image getImage(@NonNull IMarker marker) { - return null; - } - - /** - * @param marker the {@link IMarker} to get the font for - * @return The font for this particular column, or null - */ - @Nullable - public Font getFont(@NonNull IMarker marker) { - return null; - } - - /** - * @return true if the sort should be in ascending order. If false, sort in descending order. - */ - public boolean isAscending() { - return true; - } - - /** - * @return true if this column should be visible by default - */ - public boolean visibleByDefault() { - return true; - } - - @Override - public int compare(IMarker o1, IMarker o2) { - return getValue(o1).compareTo(getValue(o2)); - } - - // Used for default LabelProvider - @Override - public String toString() { - return getColumnHeaderText(); - } - - static class MessageColumn extends LintColumn { - - public MessageColumn(LintList list) { - super(list); - } - - @Override - public @NonNull String getColumnHeaderText() { - return "Description"; - } - - @Override - public int getPreferredCharWidth() { - return 80; - } - - @Override - public String getValue(@NonNull IMarker marker) { - return getStyledValue(marker).toString(); - } - - @Override - public StyledString getStyledValue(@NonNull IMarker marker) { - StyledString styledString = new StyledString(); - - String message = marker.getAttribute(IMarker.MESSAGE, ""); - styledString.append(message); - - int count = mList.getCount(marker); - if (count > 1) { - styledString.append(String.format(" (%2$d items)", message, count), - StyledString.COUNTER_STYLER); - } - - return styledString; - } - - @Override - public Image getImage(@NonNull IMarker marker) { - int severity = marker.getAttribute(IMarker.SEVERITY, 0); - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - switch (severity) { - case IMarker.SEVERITY_ERROR: - if (LintFix.hasFix(EclipseLintClient.getId(marker))) { - return IconFactory.getInstance().getIcon("quickfix_error"); //$NON-NLS-1$ - } - return sharedImages.getImage(ISharedImages.IMG_OBJS_ERROR_TSK); - case IMarker.SEVERITY_WARNING: - if (LintFix.hasFix(EclipseLintClient.getId(marker))) { - return IconFactory.getInstance().getIcon("quickfix_warning"); //$NON-NLS-1$ - } - return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK); - case IMarker.SEVERITY_INFO: - return sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK); - default: - return null; - } - } - - @Override - public Font getFont(@NonNull IMarker marker) { - int severity = marker.getAttribute(IMarker.SEVERITY, 0); - if (severity == IMarker.SEVERITY_ERROR) { - return JFaceResources.getFontRegistry().getBold( - JFaceResources.DEFAULT_FONT); - } - - return null; - } - - @Override - public boolean isAscending() { - return false; - } - - @Override - public int compare(IMarker marker2, IMarker marker1) { - // Reversing order marker1/marker2 here since we want to use a "descending" column - // sorting marker to indicate priority. (Note that we return from isAscending too.) - - String id1 = EclipseLintClient.getId(marker1); - String id2 = EclipseLintClient.getId(marker2); - if (id1 == null || id2 == null) { - return marker1.getResource().getName().compareTo( - marker2.getResource().getName()); - } - Issue issue1 = mList.getIssue(id1); - Issue issue2 = mList.getIssue(id2); - if (issue1 == null || issue2 == null) { - // Unknown issue? Can happen if you have used a third party detector - // which is no longer available but which left a persistent marker behind - return id1.compareTo(id2); - } - int delta = mList.getSeverity(issue1).ordinal() - - mList.getSeverity(issue2).ordinal(); - if (delta != 0) { - return delta; - } - delta = issue2.getPriority() - issue1.getPriority(); - if (delta != 0) { - return delta; - } - delta = issue1.getCategory().compareTo(issue2.getCategory()); - if (delta != 0) { - return delta; - } - delta = id1.compareTo(id2); - if (delta != 0) { - return delta; - } - - IResource resource1 = marker1.getResource(); - IResource resource2 = marker2.getResource(); - - IProject project1 = resource1.getProject(); - IProject project2 = resource2.getProject(); - delta = project1.getName().compareTo(project2.getName()); - if (delta != 0) { - return delta; - } - - delta = resource1.getName().compareTo(resource2.getName()); - if (delta != 0) { - return delta; - } - - return marker1.getAttribute(IMarker.LINE_NUMBER, 0) - - marker2.getAttribute(IMarker.LINE_NUMBER, 0); - } - } - - static class CategoryColumn extends LintColumn { - - public CategoryColumn(LintList list) { - super(list); - } - - @Override - public @NonNull String getColumnHeaderText() { - return "Category"; - } - - @Override - public int getPreferredCharWidth() { - return 20; - } - - @Override - public String getValue(@NonNull IMarker marker) { - Issue issue = mList.getIssue(marker); - if (issue != null) { - return issue.getCategory().getFullName(); - } else { - return ""; - } - } - } - - static class LocationColumn extends LintColumn { - public LocationColumn(LintList list) { - super(list); - } - - @Override - public @NonNull String getColumnHeaderText() { - return "Location"; - } - - @Override - public int getPreferredCharWidth() { - return 35; - } - - @Override - public String getValue(@NonNull IMarker marker) { - return getStyledValue(marker).toString(); - } - - @Override - public StyledString getStyledValue(@NonNull IMarker marker) { - StyledString styledString = new StyledString(); - - // Combined location - IResource resource = marker.getResource(); - if (resource instanceof IProject) { - styledString.append(resource.getName()); - } else { - // Show location as Parent/File:Line in Project - styledString.append(resource.getName()); - if (resource instanceof IFile) { - int line = marker.getAttribute(IMarker.LINE_NUMBER, -1); - if (line > 1) { - styledString.append(':').append(Integer.toString(line)); - } - } else if (resource instanceof IFolder) { - styledString.append(File.separatorChar); - } - - if (!(resource.getParent() instanceof IProject)) { - styledString.append(" in "); - styledString.append(resource.getParent().getName(), - StyledString.DECORATIONS_STYLER); - } - - styledString.append(String.format(" (%1$s)", resource.getProject().getName()), - StyledString.QUALIFIER_STYLER); - } - - return styledString; - } - - @Override - public int compare(IMarker marker1, IMarker marker2) { - IResource resource1 = marker1.getResource(); - IResource resource2 = marker2.getResource(); - - IProject project1 = resource1.getProject(); - IProject project2 = resource2.getProject(); - int delta = project1.getName().compareTo(project2.getName()); - if (delta != 0) { - return delta; - } - - delta = resource1.getName().compareTo(resource2.getName()); - if (delta != 0) { - return delta; - } - - return marker1.getAttribute(IMarker.LINE_NUMBER, 0) - - marker2.getAttribute(IMarker.LINE_NUMBER, 0); - } - } - - static class FileColumn extends LintColumn { - public FileColumn(LintList list) { - super(list); - } - - @Override - public @NonNull String getColumnHeaderText() { - return "File"; - } - - @Override - public boolean visibleByDefault() { - return false; - } - - @Override - public int getPreferredCharWidth() { - return 12; - } - - @Override - public String getValue(@NonNull IMarker marker) { - if (marker.getResource() instanceof IFile) { - return marker.getResource().getName(); - } else { - return ""; - } - } - } - - static class PathColumn extends LintColumn { - public PathColumn(LintList list) { - super(list); - } - - @Override - public @NonNull String getColumnHeaderText() { - return "Path"; - } - - @Override - public boolean visibleByDefault() { - return false; - } - - @Override - public int getPreferredCharWidth() { - return 25; - } - - @Override - public String getValue(@NonNull IMarker marker) { - return marker.getResource().getFullPath().toOSString(); - } - } - - static class LineColumn extends LintColumn { - public LineColumn(LintList list) { - super(list); - } - - @Override - public @NonNull String getColumnHeaderText() { - return "Line"; - } - - @Override - public boolean visibleByDefault() { - return false; - } - - @Override - public boolean isLeftAligned() { - return false; - } - - @Override - public int getPreferredCharWidth() { - return 4; - } - - @Override - public String getValue(@NonNull IMarker marker) { - int line = getLine(marker); - if (line >= 1) { - return Integer.toString(line); - } else { - return ""; - } - } - - private int getLine(IMarker marker) { - if (marker.getResource() instanceof IFile) { - int line = marker.getAttribute(IMarker.LINE_NUMBER, -1); - return line; - } - - return -1; - } - @Override - public int compare(IMarker marker1, IMarker marker2) { - return getLine(marker1) - getLine(marker2); - } - } - - static class PriorityColumn extends LintColumn { - public PriorityColumn(LintList list) { - super(list); - } - - @Override - public @NonNull String getColumnHeaderText() { - return "Priority"; - } - - @Override - public boolean visibleByDefault() { - return false; - } - - @Override - public boolean isLeftAligned() { - return false; - } - - @Override - public int getPreferredCharWidth() { - return 2; - } - - @Override - public String getValue(@NonNull IMarker marker) { - int priority = getPriority(marker); - if (priority > 0) { - return Integer.toString(priority); - } - return ""; - } - - private int getPriority(IMarker marker) { - Issue issue = mList.getIssue(marker); - if (issue != null) { - return issue.getPriority(); - } - return 0; - } - - @Override - public int compare(IMarker marker1, IMarker marker2) { - return getPriority(marker1) - getPriority(marker2); - } - - @Override - public boolean isAscending() { - return false; - } - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintDeltaProcessor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintDeltaProcessor.java deleted file mode 100644 index ebb9a591c..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintDeltaProcessor.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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.DOT_CLASS; -import static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.EXT_JAVA; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor; -import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener; -import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.swt.widgets.Display; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Delta processor for Java files, which runs single-file lints if it finds that - * the currently active file has been updated. - */ -public class LintDeltaProcessor implements Runnable { - private List<IResource> mFiles; - private IFile mActiveFile; - - private LintDeltaProcessor() { - // Get the active editor file, if any - Display display = AdtPlugin.getDisplay(); - if (display == null || display.isDisposed()) { - return; - } - if (display.getThread() != Thread.currentThread()) { - display.syncExec(this); - } else { - run(); - } - } - - /** - * Creates a new {@link LintDeltaProcessor} - * - * @return a visitor - */ - @NonNull - public static LintDeltaProcessor create() { - return new LintDeltaProcessor(); - } - - /** - * Process the given delta: update lint on any Java source and class files found. - * - * @param delta the delta describing recently changed files - */ - public void process(@NonNull IResourceDelta delta) { - if (mActiveFile == null || !mActiveFile.getName().endsWith(DOT_JAVA)) { - return; - } - - mFiles = new ArrayList<IResource>(); - gatherFiles(delta); - - if (!mFiles.isEmpty()) { - EclipseLintRunner.startLint(mFiles, mActiveFile, null, - false /*fatalOnly*/, false /*show*/); - } - } - - /** - * Process edits in the given file: update lint on the Java source provided - * it's the active file. - * - * @param file the file that was changed - */ - public void process(@NonNull IFile file) { - if (mActiveFile == null || !mActiveFile.getName().endsWith(DOT_JAVA)) { - return; - } - - if (file.equals(mActiveFile)) { - mFiles = Collections.<IResource>singletonList(file); - EclipseLintRunner.startLint(mFiles, mActiveFile, null, - false /*fatalOnly*/, false /*show*/); - } - } - - /** - * Collect .java and .class files to be run in lint. Only collects files - * that match the active editor. - */ - private void gatherFiles(@NonNull IResourceDelta delta) { - IResource resource = delta.getResource(); - String name = resource.getName(); - if (name.endsWith(DOT_JAVA)) { - if (resource.equals(mActiveFile)) { - mFiles.add(resource); - } - } else if (name.endsWith(DOT_CLASS)) { - // Make sure this class corresponds to the .java file, meaning it has - // the same basename, or that it is an inner class of a class that - // matches the same basename. (We could potentially make sure the package - // names match too, but it's unlikely that the class names match without a - // package match, and there's no harm in including some extra classes here, - // since lint will resolve full paths and the resource markers won't go - // to the wrong place, we simply end up analyzing some extra files.) - String className = mActiveFile.getName(); - if (name.regionMatches(0, className, 0, className.length() - DOT_JAVA.length())) { - if (name.length() == className.length() - DOT_JAVA.length() + DOT_CLASS.length() - || name.charAt(className.length() - DOT_JAVA.length()) == '$') { - mFiles.add(resource); - } - } - } else { - IResourceDelta[] children = delta.getAffectedChildren(); - if (children != null && children.length > 0) { - for (IResourceDelta d : children) { - gatherFiles(d); - } - } - } - } - - @Override - public void run() { - // Get the active file: this must be run on the GUI thread - mActiveFile = AdtUtils.getActiveFile(); - } - - /** - * Start listening to the resource monitor - * - * @param resourceMonitor the resource monitor - */ - public static void startListening(@NonNull GlobalProjectMonitor resourceMonitor) { - // Add a file listener which finds out when files have changed. This is listening - // specifically for saves of Java files, in order to run incremental lint on them. - // Note that the {@link PostCompilerBuilder} already handles incremental lint files - // on Java files - and runs it for both the .java and .class files. - // - // However, if Project > Build Automatically is turned off, then the PostCompilerBuilder - // isn't run after a save. THAT's what the below is for: it will run and *only* - // run lint incrementally if build automatically is off. - assert sListener == null; // Should only be called once on plugin activation - sListener = new IFileListener() { - @Override - public void fileChanged(@NonNull IFile file, - @NonNull IMarkerDelta[] markerDeltas, - int kind, @Nullable String extension, int flags, boolean isAndroidProject) { - if (!isAndroidProject || flags == IResourceDelta.MARKERS) { - // If not an Android project or ONLY the markers changed. - // Ignore these since they happen - // when we add markers for lint errors found in the current file, - // which would cause us to repeatedly enter this method over and over - // again. - return; - } - if (EXT_JAVA.equals(extension) - && !ResourceManager.isAutoBuilding() - && AdtPrefs.getPrefs().isLintOnSave()) { - LintDeltaProcessor.create().process(file); - } - } - }; - resourceMonitor.addFileListener(sListener, IResourceDelta.ADDED | IResourceDelta.CHANGED); - } - - /** - * Stop listening to the resource monitor - * - * @param resourceMonitor the resource monitor - */ - public static void stopListening(@NonNull GlobalProjectMonitor resourceMonitor) { - assert sListener != null; - resourceMonitor.removeFileListener(sListener); - sListener = null; - } - - private static IFileListener sListener; -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintEditAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintEditAction.java deleted file mode 100644 index bf05ce0b1..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintEditAction.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 com.android.annotations.NonNull; -import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DelegatingAction; - -import org.eclipse.jface.action.IAction; -import org.eclipse.swt.widgets.Event; - -/** - * Action intended to wrap an existing XML editor action, and then runs lint after - * the edit. - */ -public class LintEditAction extends DelegatingAction { - private final AndroidXmlEditor mEditor; - - /** - * Creates a new {@link LintEditAction} associated with the given editor to - * wrap the given action - * - * @param action the action to be wrapped - * @param editor the editor associated with the action - */ - public LintEditAction(@NonNull IAction action, @NonNull AndroidXmlEditor editor) { - super(action); - mEditor = editor; - } - - @Override - public void runWithEvent(Event event) { - super.runWithEvent(event); - mEditor.runEditHooks(); - } -} 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 deleted file mode 100644 index 366e94945..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java deleted file mode 100644 index da100850a..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java +++ /dev/null @@ -1,563 +0,0 @@ -/* - * 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 static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.DOT_XML; - -import com.android.ide.eclipse.adt.AdtConstants; -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.preferences.AdtPrefs; -import com.android.tools.lint.client.api.Configuration; -import com.android.tools.lint.client.api.DefaultConfiguration; -import com.android.tools.lint.client.api.IssueRegistry; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.TextFormat; -import com.android.tools.lint.detector.api.Project; -import com.android.tools.lint.detector.api.Severity; -import com.android.utils.SdkUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.Region; -import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.text.contentassist.IContextInformation; -import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; -import org.eclipse.jface.text.quickassist.IQuickAssistProcessor; -import org.eclipse.jface.text.source.Annotation; -import org.eclipse.jface.text.source.ISourceViewer; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IMarkerResolution; -import org.eclipse.ui.IMarkerResolution2; -import org.eclipse.ui.IMarkerResolutionGenerator2; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.part.FileEditorInput; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A quickfix and marker resolution for disabling lint checks, and any - * IDE specific implementations for fixing the warnings. - * <p> - * I would really like for this quickfix to show up as a light bulb on top of the error - * icon in the editor, and I've spent a whole day trying to make it work. I did not - * succeed, but here are the steps I tried in case I want to pick up the work again - * later: - * <ul> - * <li> - * The WST has some support for quick fixes, and I came across some forum posts - * referencing the ability to show light bulbs. However, it turns out that the - * quickfix support for annotations in WST is hardcoded to source validation - * errors *only*. - * <li> - * I tried defining my own editor annotations, and customizing the icon directly - * by either setting an icon or using the image provider. This works fine - * if I make my marker be a new independent marker type. However, whenever I - * switch the marker type back to extend the "Problem" type, then the icon reverts - * back to the standard error icon and it ignores my custom settings. - * And if I switch away from the Problems marker type, then the errors no longer - * show up in the Problems view. (I also tried extending the JDT marker but that - * still didn't work.) - * <li> - * It looks like only JDT handles quickfix icons. It has a bunch of custom code - * to handle this, along with its own Annotation subclass used by the editor. - * I tried duplicating some of this by subclassing StructuredTextEditor, but - * it was evident that I'd have to pull in a *huge* amount of duplicated code to - * make this work, which seems risky given that all this is internal code that - * can change from one Eclipse version to the next. - * </ul> - * It looks like our best bet would be to reconsider whether these should show up - * in the Problems view; perhaps we should use a custom view for these. That would also - * make marker management more obvious. - */ -@SuppressWarnings("restriction") // DOM model -public class LintFixGenerator implements IMarkerResolutionGenerator2, IQuickAssistProcessor { - /** Constructs a new {@link LintFixGenerator} */ - public LintFixGenerator() { - } - - // ---- Implements IMarkerResolutionGenerator2 ---- - - @Override - public boolean hasResolutions(IMarker marker) { - try { - assert marker.getType().equals(AdtConstants.MARKER_LINT); - } catch (CoreException e) { - } - - return true; - } - - @Override - public IMarkerResolution[] getResolutions(IMarker marker) { - String id = marker.getAttribute(EclipseLintRunner.MARKER_CHECKID_PROPERTY, - ""); //$NON-NLS-1$ - IResource resource = marker.getResource(); - - List<IMarkerResolution> resolutions = new ArrayList<IMarkerResolution>(); - - if (resource.getName().endsWith(DOT_JAVA)) { - AddSuppressAnnotation.createFixes(marker, id, resolutions); - } - - resolutions.add(new MoreInfoProposal(id, marker.getAttribute(IMarker.MESSAGE, null))); - resolutions.add(new SuppressProposal(resource, id, false)); - resolutions.add(new SuppressProposal(resource.getProject(), id, true /* all */)); - resolutions.add(new SuppressProposal(resource, id, true /* all */)); - resolutions.add(new ClearMarkersProposal(resource, true /* all */)); - - if (resolutions.size() > 0) { - return resolutions.toArray(new IMarkerResolution[resolutions.size()]); - } - - return null; - } - - // ---- Implements IQuickAssistProcessor ---- - - @Override - public String getErrorMessage() { - return "Disable Lint Error"; - } - - @Override - public boolean canFix(Annotation annotation) { - return true; - } - - @Override - public boolean canAssist(IQuickAssistInvocationContext invocationContext) { - return true; - } - - @Override - public ICompletionProposal[] computeQuickAssistProposals( - IQuickAssistInvocationContext invocationContext) { - ISourceViewer sourceViewer = invocationContext.getSourceViewer(); - AndroidXmlEditor editor = AndroidXmlEditor.fromTextViewer(sourceViewer); - if (editor != null) { - IFile file = editor.getInputFile(); - if (file == null) { - return null; - } - IDocument document = sourceViewer.getDocument(); - List<IMarker> markers = AdtUtils.findMarkersOnLine(AdtConstants.MARKER_LINT, - file, document, invocationContext.getOffset()); - List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>(); - if (markers.size() > 0) { - for (IMarker marker : markers) { - String id = marker.getAttribute(EclipseLintRunner.MARKER_CHECKID_PROPERTY, - ""); //$NON-NLS-1$ - - // TODO: Allow for more than one fix? - List<LintFix> fixes = LintFix.getFixes(id, marker); - if (fixes != null) { - for (LintFix fix : fixes) { - proposals.add(fix); - } - } - - String message = marker.getAttribute(IMarker.MESSAGE, null); - proposals.add(new MoreInfoProposal(id, message)); - - proposals.addAll(AddSuppressAttribute.createFixes(editor, marker, id)); - proposals.add(new SuppressProposal(file, id, false)); - proposals.add(new SuppressProposal(file.getProject(), id, true /* all */)); - proposals.add(new SuppressProposal(file, id, true /* all */)); - - proposals.add(new ClearMarkersProposal(file, true /* all */)); - } - } - if (proposals.size() > 0) { - return proposals.toArray(new ICompletionProposal[proposals.size()]); - } - } - - return null; - } - - /** - * Suppress the given detector, and rerun the checks on the file - * - * @param id the id of the detector to be suppressed, or null - * @param updateMarkers if true, update all markers - * @param resource the resource associated with the markers - * @param thisFileOnly if true, only suppress this issue in this file - */ - public static void suppressDetector(String id, boolean updateMarkers, IResource resource, - boolean thisFileOnly) { - IssueRegistry registry = EclipseLintClient.getRegistry(); - Issue issue = registry.getIssue(id); - if (issue != null) { - EclipseLintClient mClient = new EclipseLintClient(registry, - Collections.singletonList(resource), null, false); - Project project = null; - IProject eclipseProject = resource.getProject(); - if (eclipseProject != null) { - File dir = AdtUtils.getAbsolutePath(eclipseProject).toFile(); - project = mClient.getProject(dir, dir); - } - Configuration configuration = mClient.getConfigurationFor(project); - if (thisFileOnly && configuration instanceof DefaultConfiguration) { - File file = AdtUtils.getAbsolutePath(resource).toFile(); - ((DefaultConfiguration) configuration).ignore(issue, file); - } else { - configuration.setSeverity(issue, Severity.IGNORE); - } - } - - if (updateMarkers) { - EclipseLintClient.removeMarkers(resource, id); - } - } - - /** - * Adds a suppress lint annotation or attribute depending on whether the - * error is in a Java or XML file. - * - * @param marker the marker pointing to the error to be suppressed - */ - public static void addSuppressAnnotation(IMarker marker) { - String id = EclipseLintClient.getId(marker); - if (id != null) { - IResource resource = marker.getResource(); - if (!(resource instanceof IFile)) { - return; - } - IFile file = (IFile) resource; - boolean isJava = file.getName().endsWith(DOT_JAVA); - boolean isXml = SdkUtils.endsWith(file.getName(), DOT_XML); - if (!isJava && !isXml) { - return; - } - - try { - // See if the current active file is the one containing this marker; - // if so we can take some shortcuts - IEditorPart activeEditor = AdtUtils.getActiveEditor(); - IEditorPart part = null; - if (activeEditor != null) { - IEditorInput input = activeEditor.getEditorInput(); - if (input instanceof FileEditorInput - && ((FileEditorInput)input).getFile().equals(file)) { - part = activeEditor; - } - } - if (part == null) { - IRegion region = null; - int start = marker.getAttribute(IMarker.CHAR_START, -1); - int end = marker.getAttribute(IMarker.CHAR_END, -1); - if (start != -1 && end != -1) { - region = new Region(start, end - start); - } - part = AdtPlugin.openFile(file, region, true /* showEditor */); - } - - if (isJava) { - List<IMarkerResolution> resolutions = new ArrayList<IMarkerResolution>(); - AddSuppressAnnotation.createFixes(marker, id, resolutions); - if (resolutions.size() > 0) { - resolutions.get(0).run(marker); - } - } else { - assert isXml; - if (part instanceof AndroidXmlEditor) { - AndroidXmlEditor editor = (AndroidXmlEditor) part; - List<AddSuppressAttribute> fixes = AddSuppressAttribute.createFixes(editor, - marker, id); - if (fixes.size() > 0) { - IStructuredDocument document = editor.getStructuredDocument(); - fixes.get(0).apply(document); - } - } - } - } catch (PartInitException pie) { - AdtPlugin.log(pie, null); - } - } - } - - private static class SuppressProposal implements ICompletionProposal, IMarkerResolution2 { - private final String mId; - private final boolean mGlobal; - private final IResource mResource; - - private SuppressProposal(IResource resource, String check, boolean global) { - mResource = resource; - mId = check; - mGlobal = global; - } - - private void perform() { - suppressDetector(mId, true, mResource, !mGlobal); - } - - @Override - public String getDisplayString() { - if (mResource instanceof IProject) { - return "Disable Check in This Project"; - } else if (mGlobal) { - return "Disable Check"; - } else { - return "Disable Check in This File Only"; - } - } - - // ---- Implements MarkerResolution2 ---- - - @Override - public String getLabel() { - return getDisplayString(); - } - - @Override - public void run(IMarker marker) { - perform(); - } - - @Override - public String getDescription() { - return getAdditionalProposalInfo(); - } - - // ---- Implements ICompletionProposal ---- - - @Override - public void apply(IDocument document) { - perform(); - } - - @Override - public Point getSelection(IDocument document) { - return null; - } - - @Override - public String getAdditionalProposalInfo() { - StringBuilder sb = new StringBuilder(200); - if (mResource instanceof IProject) { - sb.append("Suppresses this type of lint warning in the current project only."); - } else if (mGlobal) { - sb.append("Suppresses this type of lint warning in all files."); - } else { - sb.append("Suppresses this type of lint warning in the current file only."); - } - sb.append("<br><br>"); //$NON-NLS-1$ - sb.append("You can re-enable checks from the \"Android > Lint Error Checking\" preference page."); - - return sb.toString(); - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_OBJS_WARN_TSK); - } - - @Override - public IContextInformation getContextInformation() { - return null; - } - } - - private static class ClearMarkersProposal implements ICompletionProposal, IMarkerResolution2 { - private final boolean mGlobal; - private final IResource mResource; - - public ClearMarkersProposal(IResource resource, boolean global) { - mResource = resource; - mGlobal = global; - } - - private void perform() { - IResource resource = mGlobal ? mResource.getProject() : mResource; - EclipseLintClient.clearMarkers(resource); - } - - @Override - public String getDisplayString() { - return mGlobal ? "Clear All Lint Markers" : "Clear Markers in This File Only"; - } - - // ---- Implements MarkerResolution2 ---- - - @Override - public String getLabel() { - return getDisplayString(); - } - - @Override - public void run(IMarker marker) { - perform(); - } - - @Override - public String getDescription() { - return getAdditionalProposalInfo(); - } - - // ---- Implements ICompletionProposal ---- - - @Override - public void apply(IDocument document) { - perform(); - } - - @Override - public Point getSelection(IDocument document) { - return null; - } - - @Override - public String getAdditionalProposalInfo() { - StringBuilder sb = new StringBuilder(200); - if (mGlobal) { - sb.append("Clears all lint warning markers from the project."); - } else { - sb.append("Clears all lint warnings from this file."); - } - sb.append("<br><br>"); //$NON-NLS-1$ - sb.append("This temporarily hides the problem, but does not suppress it. " + - "Running Lint again can bring the error back."); - if (AdtPrefs.getPrefs().isLintOnSave()) { - sb.append(' '); - sb.append("This will happen the next time the file is saved since lint-on-save " + - "is enabled. You can turn this off in the \"Lint Error Checking\" " + - "preference page."); - } - - return sb.toString(); - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_ELCL_REMOVE); - } - - @Override - public IContextInformation getContextInformation() { - return null; - } - } - - private static class MoreInfoProposal implements ICompletionProposal, IMarkerResolution2 { - private final String mId; - private final String mMessage; - - public MoreInfoProposal(String id, String message) { - mId = id; - mMessage = message; - } - - private void perform() { - Issue issue = EclipseLintClient.getRegistry().getIssue(mId); - assert issue != null : mId; - - StringBuilder sb = new StringBuilder(300); - sb.append(mMessage); - sb.append('\n').append('\n'); - sb.append("Issue Explanation:"); - sb.append('\n'); - String explanation = issue.getExplanation(TextFormat.TEXT); - if (explanation != null && !explanation.isEmpty()) { - sb.append('\n'); - sb.append(explanation); - } else { - sb.append(issue.getBriefDescription(TextFormat.TEXT)); - } - - if (issue.getMoreInfo() != null) { - sb.append('\n').append('\n'); - sb.append("More Information: "); - sb.append(issue.getMoreInfo()); - } - - MessageDialog.openInformation(AdtPlugin.getShell(), "More Info", - sb.toString()); - } - - @Override - public String getDisplayString() { - return String.format("Explain Issue (%1$s)", mId); - } - - // ---- Implements MarkerResolution2 ---- - - @Override - public String getLabel() { - return getDisplayString(); - } - - @Override - public void run(IMarker marker) { - perform(); - } - - @Override - public String getDescription() { - return getAdditionalProposalInfo(); - } - - // ---- Implements ICompletionProposal ---- - - @Override - public void apply(IDocument document) { - perform(); - } - - @Override - public Point getSelection(IDocument document) { - return null; - } - - @Override - public String getAdditionalProposalInfo() { - return "Provides more information about this issue." - + "<br><br>" //$NON-NLS-1$ - + EclipseLintClient.getRegistry().getIssue(mId).getExplanation( - TextFormat.HTML); - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_OBJS_INFO_TSK); - } - - @Override - public IContextInformation getContextInformation() { - return null; - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintJob.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintJob.java deleted file mode 100644 index 51fa2d145..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintJob.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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.DOT_CLASS; -import static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.DOT_XML; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.tools.lint.client.api.IssueRegistry; -import com.android.tools.lint.client.api.LintDriver; -import com.android.tools.lint.client.api.LintRequest; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.Scope; -import com.android.utils.SdkUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.IJobManager; -import org.eclipse.core.runtime.jobs.Job; - -import java.io.File; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -/** Job to check lint on a set of resources */ -public final class LintJob extends Job { - /** Job family */ - private static final Object FAMILY_RUN_LINT = new Object(); - private final EclipseLintClient mClient; - private final List<? extends IResource> mResources; - private final IResource mSource; - private final IssueRegistry mRegistry; - private LintDriver mLint; - private boolean mFatal; - - public LintJob( - @NonNull EclipseLintClient client, - @NonNull List<? extends IResource> resources, - @Nullable IResource source, - @NonNull IssueRegistry registry) { - super("Running Android Lint"); - mClient = client; - mResources = resources; - mSource = source; - mRegistry = registry; - } - - public LintJob( - @NonNull EclipseLintClient client, - @NonNull List<? extends IResource> resources, - @Nullable IResource source) { - this(client, resources, source, EclipseLintClient.getRegistry()); - } - - @Override - public boolean belongsTo(Object family) { - return family == FAMILY_RUN_LINT; - } - - @Override - protected void canceling() { - super.canceling(); - if (mLint != null) { - mLint.cancel(); - } - } - - @Override - @NonNull - protected IStatus run(IProgressMonitor monitor) { - try { - monitor.beginTask("Looking for errors", IProgressMonitor.UNKNOWN); - EnumSet<Scope> scope = null; - List<File> files = new ArrayList<File>(mResources.size()); - for (IResource resource : mResources) { - File file = AdtUtils.getAbsolutePath(resource).toFile(); - files.add(file); - - if (resource instanceof IProject && mSource == null) { - scope = Scope.ALL; - } else { - String name = resource.getName(); - if (SdkUtils.endsWithIgnoreCase(name, DOT_XML)) { - if (name.equals(SdkConstants.FN_ANDROID_MANIFEST_XML)) { - scope = EnumSet.of(Scope.MANIFEST); - } else { - scope = Scope.RESOURCE_FILE_SCOPE; - } - } else if (name.endsWith(DOT_JAVA) && resource instanceof IFile) { - if (scope != null) { - if (!scope.contains(Scope.JAVA_FILE)) { - scope = EnumSet.copyOf(scope); - scope.add(Scope.JAVA_FILE); - } - } else { - scope = Scope.JAVA_FILE_SCOPE; - } - } else if (name.endsWith(DOT_CLASS) && resource instanceof IFile) { - if (scope != null) { - if (!scope.contains(Scope.CLASS_FILE)) { - scope = EnumSet.copyOf(scope); - scope.add(Scope.CLASS_FILE); - } - } else { - scope = Scope.CLASS_FILE_SCOPE; - } - } else { - return new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, Status.ERROR, - "Only XML & Java files are supported for single file lint", null); //$NON-NLS-1$ - } - } - } - if (scope == null) { - scope = Scope.ALL; - } - if (mSource == null) { - assert !Scope.checkSingleFile(scope) : scope + " with " + mResources; - } - // Check single file? - if (mSource != null) { - // Delete specific markers - IMarker[] markers = EclipseLintClient.getMarkers(mSource); - for (IMarker marker : markers) { - String id = marker.getAttribute(EclipseLintRunner.MARKER_CHECKID_PROPERTY, ""); - Issue issue = mRegistry.getIssue(id); - if (issue == null) { - continue; - } - if (issue.getImplementation().isAdequate(scope)) { - marker.delete(); - } - } - mClient.setSearchForSuperClasses(true); - } else { - EclipseLintClient.clearMarkers(mResources); - } - - mLint = new LintDriver(mRegistry, mClient); - mLint.analyze(new LintRequest(mClient, files).setScope(scope)); - mFatal = mClient.hasFatalErrors(); - return Status.OK_STATUS; - } catch (Exception e) { - return new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, Status.ERROR, - "Failed", e); //$NON-NLS-1$ - } finally { - if (monitor != null) { - monitor.done(); - } - } - } - - /** - * Returns true if a fatal error was encountered - * - * @return true if a fatal error was encountered - */ - public boolean isFatal() { - return mFatal; - } - - /** - * Returns the associated lint client - * - * @return the associated lint client - */ - @NonNull - public EclipseLintClient getLintClient() { - return mClient; - } - - /** Returns the current lint jobs, if any (never returns null but array may be empty) */ - @NonNull - static Job[] getCurrentJobs() { - IJobManager jobManager = Job.getJobManager(); - return jobManager.find(LintJob.FAMILY_RUN_LINT); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintList.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintList.java deleted file mode 100644 index ccb04bb6b..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintList.java +++ /dev/null @@ -1,979 +0,0 @@ -/* - * 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.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.LayoutActionBar; -import com.android.tools.lint.client.api.Configuration; -import com.android.tools.lint.client.api.IssueRegistry; -import com.android.tools.lint.client.api.LintClient; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.Severity; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IMarkerDelta; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.viewers.ColumnPixelData; -import org.eclipse.jface.viewers.ColumnWeightData; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.StyledCellLabelProvider; -import org.eclipse.jface.viewers.StyledString; -import org.eclipse.jface.viewers.TableLayout; -import org.eclipse.jface.viewers.TreeNodeContentProvider; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.TreeViewerColumn; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerCell; -import org.eclipse.jface.viewers.ViewerComparator; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.BusyIndicator; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.ControlListener; -import org.eclipse.swt.events.PaintEvent; -import org.eclipse.swt.events.PaintListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.events.TreeEvent; -import org.eclipse.swt.events.TreeListener; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; -import org.eclipse.swt.widgets.TreeItem; -import org.eclipse.ui.IMemento; -import org.eclipse.ui.IWorkbenchPartSite; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.progress.IWorkbenchSiteProgressService; -import org.eclipse.ui.progress.WorkbenchJob; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * A tree-table widget which shows a list of lint warnings for an underlying - * {@link IResource} such as a file, a project, or a list of projects. - */ -class LintList extends Composite implements IResourceChangeListener, ControlListener { - private static final Object UPDATE_MARKERS_FAMILY = new Object(); - - // For persistence: - private static final String KEY_WIDTHS = "lintColWidth"; //$NON-NLS-1$ - private static final String KEY_VISIBLE = "lintColVisible"; //$NON-NLS-1$ - // Mapping SWT TreeColumns to LintColumns - private static final String KEY_COLUMN = "lintColumn"; //$NON-NLS-1$ - - private final IWorkbenchPartSite mSite; - private final TreeViewer mTreeViewer; - private final Tree mTree; - private Set<String> mExpandedIds; - private ContentProvider mContentProvider; - private String mSelectedId; - private List<? extends IResource> mResources; - private Configuration mConfiguration; - private final boolean mSingleFile; - private int mErrorCount; - private int mWarningCount; - private final UpdateMarkersJob mUpdateMarkersJob = new UpdateMarkersJob(); - private final IssueRegistry mRegistry; - private final IMemento mMemento; - private final LintColumn mMessageColumn = new LintColumn.MessageColumn(this); - private final LintColumn mLineColumn = new LintColumn.LineColumn(this); - private final LintColumn[] mColumns = new LintColumn[] { - mMessageColumn, - new LintColumn.PriorityColumn(this), - new LintColumn.CategoryColumn(this), - new LintColumn.LocationColumn(this), - new LintColumn.FileColumn(this), - new LintColumn.PathColumn(this), - mLineColumn - }; - private LintColumn[] mVisibleColumns; - - LintList(IWorkbenchPartSite site, Composite parent, IMemento memento, boolean singleFile) { - super(parent, SWT.NONE); - mSingleFile = singleFile; - mMemento = memento; - mSite = site; - mRegistry = EclipseLintClient.getRegistry(); - - GridLayout gridLayout = new GridLayout(1, false); - gridLayout.marginWidth = 0; - gridLayout.marginHeight = 0; - setLayout(gridLayout); - - mTreeViewer = new TreeViewer(this, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI); - mTree = mTreeViewer.getTree(); - mTree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - - createColumns(); - mTreeViewer.setComparator(new TableComparator()); - setSortIndicators(); - - mContentProvider = new ContentProvider(); - mTreeViewer.setContentProvider(mContentProvider); - - mTree.setLinesVisible(true); - mTree.setHeaderVisible(true); - mTree.addControlListener(this); - - ResourcesPlugin.getWorkspace().addResourceChangeListener( - this, - IResourceChangeEvent.POST_CHANGE - | IResourceChangeEvent.PRE_BUILD - | IResourceChangeEvent.POST_BUILD); - - // Workaround for https://bugs.eclipse.org/341865 - mTree.addPaintListener(new PaintListener() { - @Override - public void paintControl(PaintEvent e) { - mTreePainted = true; - mTreeViewer.getTree().removePaintListener(this); - } - }); - - // Remember the most recently selected id category such that we can - // attempt to reselect it after a refresh - mTree.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - List<IMarker> markers = getSelectedMarkers(); - if (markers.size() > 0) { - mSelectedId = EclipseLintClient.getId(markers.get(0)); - } - } - }); - mTree.addTreeListener(new TreeListener() { - @Override - public void treeExpanded(TreeEvent e) { - Object data = e.item.getData(); - if (data instanceof IMarker) { - String id = EclipseLintClient.getId((IMarker) data); - if (id != null) { - if (mExpandedIds == null) { - mExpandedIds = new HashSet<String>(); - } - mExpandedIds.add(id); - } - } - } - - @Override - public void treeCollapsed(TreeEvent e) { - if (mExpandedIds != null) { - Object data = e.item.getData(); - if (data instanceof IMarker) { - String id = EclipseLintClient.getId((IMarker) data); - if (id != null) { - mExpandedIds.remove(id); - } - } - } - } - }); - } - - private boolean mTreePainted; - - private void updateColumnWidths() { - Rectangle r = mTree.getClientArea(); - int availableWidth = r.width; - // Add all available size to the first column - for (int i = 1; i < mTree.getColumnCount(); i++) { - TreeColumn column = mTree.getColumn(i); - availableWidth -= column.getWidth(); - } - if (availableWidth > 100) { - mTree.getColumn(0).setWidth(availableWidth); - } - } - - public void setResources(List<? extends IResource> resources) { - mResources = resources; - - mConfiguration = null; - for (IResource resource : mResources) { - IProject project = resource.getProject(); - if (project != null) { - // For logging only - LintClient client = new EclipseLintClient(null, null, null, false); - mConfiguration = ProjectLintConfiguration.get(client, project, false); - break; - } - } - if (mConfiguration == null) { - mConfiguration = GlobalLintConfiguration.get(); - } - - List<IMarker> markerList = getMarkers(); - mTreeViewer.setInput(markerList); - if (mSingleFile) { - expandAll(); - } - - // Selecting the first item isn't a good idea since it may not be the first - // item shown in the table (since it does its own sorting), and furthermore we - // may not have all the data yet; this is called when scanning begins, not when - // it's done: - //if (mTree.getItemCount() > 0) { - // mTree.select(mTree.getItem(0)); - //} - - updateColumnWidths(); // in case mSingleFile changed - } - - /** Select the first item */ - public void selectFirst() { - if (mTree.getItemCount() > 0) { - mTree.select(mTree.getItem(0)); - } - } - - private List<IMarker> getMarkers() { - mErrorCount = mWarningCount = 0; - List<IMarker> markerList = new ArrayList<IMarker>(); - if (mResources != null) { - for (IResource resource : mResources) { - IMarker[] markers = EclipseLintClient.getMarkers(resource); - for (IMarker marker : markers) { - markerList.add(marker); - int severity = marker.getAttribute(IMarker.SEVERITY, 0); - if (severity == IMarker.SEVERITY_ERROR) { - mErrorCount++; - } else if (severity == IMarker.SEVERITY_WARNING) { - mWarningCount++; - } - } - } - - // No need to sort the marker list here; it will be sorted by the tree table model - } - return markerList; - } - - public int getErrorCount() { - return mErrorCount; - } - - public int getWarningCount() { - return mWarningCount; - } - - @Override - protected void checkSubclass() { - // Disable the check that prevents subclassing of SWT components - } - - public void addSelectionListener(SelectionListener listener) { - mTree.addSelectionListener(listener); - } - - public void refresh() { - mTreeViewer.refresh(); - } - - public List<IMarker> getSelectedMarkers() { - TreeItem[] selection = mTree.getSelection(); - List<IMarker> markers = new ArrayList<IMarker>(selection.length); - for (TreeItem item : selection) { - Object data = item.getData(); - if (data instanceof IMarker) { - markers.add((IMarker) data); - } - } - - return markers; - } - - @Override - public void dispose() { - cancelJobs(); - ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); - super.dispose(); - } - - private class ContentProvider extends TreeNodeContentProvider { - private Map<Object, Object[]> mChildren; - private Map<IMarker, Integer> mTypeCount; - private IMarker[] mTopLevels; - - @Override - public Object[] getElements(Object inputElement) { - if (inputElement == null) { - mTypeCount = null; - return new IMarker[0]; - } - - @SuppressWarnings("unchecked") - List<IMarker> list = (List<IMarker>) inputElement; - - // Partition the children such that at the top level we have one - // marker of each type, and below we have all the duplicates of - // each one of those errors. And for errors with multiple locations, - // there is a third level. - Multimap<String, IMarker> types = ArrayListMultimap.<String, IMarker>create(100, 20); - for (IMarker marker : list) { - String id = EclipseLintClient.getId(marker); - types.put(id, marker); - } - - Set<String> ids = types.keySet(); - - mChildren = new HashMap<Object, Object[]>(ids.size()); - mTypeCount = new HashMap<IMarker, Integer>(ids.size()); - - List<IMarker> topLevel = new ArrayList<IMarker>(ids.size()); - for (String id : ids) { - Collection<IMarker> markers = types.get(id); - int childCount = markers.size(); - - // Must sort the list items in order to have a stable first item - // (otherwise preserving expanded paths etc won't work) - TableComparator sorter = getTableSorter(); - IMarker[] array = markers.toArray(new IMarker[markers.size()]); - sorter.sort(mTreeViewer, array); - - IMarker topMarker = array[0]; - mTypeCount.put(topMarker, childCount); - topLevel.add(topMarker); - - IMarker[] children = Arrays.copyOfRange(array, 1, array.length); - mChildren.put(topMarker, children); - } - - mTopLevels = topLevel.toArray(new IMarker[topLevel.size()]); - return mTopLevels; - } - - @Override - public boolean hasChildren(Object element) { - Object[] children = mChildren != null ? mChildren.get(element) : null; - return children != null && children.length > 0; - } - - @Override - public Object[] getChildren(Object parentElement) { - Object[] children = mChildren.get(parentElement); - if (children != null) { - return children; - } - - return new Object[0]; - } - - @Override - public Object getParent(Object element) { - return null; - } - - public int getCount(IMarker marker) { - if (mTypeCount != null) { - Integer count = mTypeCount.get(marker); - if (count != null) { - return count.intValue(); - } - } - - return -1; - } - - IMarker[] getTopMarkers() { - return mTopLevels; - } - } - - private class LintColumnLabelProvider extends StyledCellLabelProvider { - private LintColumn mColumn; - - LintColumnLabelProvider(LintColumn column) { - mColumn = column; - } - - @Override - public void update(ViewerCell cell) { - Object element = cell.getElement(); - cell.setImage(mColumn.getImage((IMarker) element)); - StyledString styledString = mColumn.getStyledValue((IMarker) element); - if (styledString == null) { - cell.setText(mColumn.getValue((IMarker) element)); - cell.setStyleRanges(null); - } else { - cell.setText(styledString.toString()); - cell.setStyleRanges(styledString.getStyleRanges()); - } - super.update(cell); - } - } - - TreeViewer getTreeViewer() { - return mTreeViewer; - } - - Tree getTree() { - return mTree; - } - - // ---- Implements IResourceChangeListener ---- - - @Override - public void resourceChanged(IResourceChangeEvent event) { - if (mResources == null) { - return; - } - IMarkerDelta[] deltas = event.findMarkerDeltas(AdtConstants.MARKER_LINT, true); - if (deltas.length > 0) { - // Update immediately for POST_BUILD events, otherwise do an unconditional - // update after 30 seconds. This matches the logic in Eclipse's ProblemView - // (see the MarkerView class). - if (event.getType() == IResourceChangeEvent.POST_BUILD) { - cancelJobs(); - getProgressService().schedule(mUpdateMarkersJob, 100); - } else { - IWorkbenchSiteProgressService progressService = getProgressService(); - if (progressService == null) { - mUpdateMarkersJob.schedule(30000); - } else { - getProgressService().schedule(mUpdateMarkersJob, 30000); - } - } - } - } - - // ---- Implements ControlListener ---- - - @Override - public void controlMoved(ControlEvent e) { - } - - @Override - public void controlResized(ControlEvent e) { - updateColumnWidths(); - } - - // ---- Updating Markers ---- - - private void cancelJobs() { - mUpdateMarkersJob.cancel(); - } - - protected IWorkbenchSiteProgressService getProgressService() { - if (mSite != null) { - Object siteService = mSite.getAdapter(IWorkbenchSiteProgressService.class); - if (siteService != null) { - return (IWorkbenchSiteProgressService) siteService; - } - } - return null; - } - - private class UpdateMarkersJob extends WorkbenchJob { - UpdateMarkersJob() { - super("Updating Lint Markers"); - setSystem(true); - } - - @Override - public IStatus runInUIThread(IProgressMonitor monitor) { - if (mTree.isDisposed()) { - return Status.CANCEL_STATUS; - } - - mTreeViewer.setInput(null); - List<IMarker> markerList = getMarkers(); - if (markerList.size() == 0) { - LayoutEditorDelegate delegate = - LayoutEditorDelegate.fromEditor(AdtUtils.getActiveEditor()); - if (delegate != null) { - GraphicalEditorPart g = delegate.getGraphicalEditor(); - assert g != null; - LayoutActionBar bar = g == null ? null : g.getLayoutActionBar(); - assert bar != null; - if (bar != null) { - bar.updateErrorIndicator(); - } - } - } - // Trigger selection update - Event updateEvent = new Event(); - updateEvent.widget = mTree; - mTree.notifyListeners(SWT.Selection, updateEvent); - mTreeViewer.setInput(markerList); - mTreeViewer.refresh(); - - if (mExpandedIds != null) { - List<IMarker> expanded = new ArrayList<IMarker>(mExpandedIds.size()); - IMarker[] topMarkers = mContentProvider.getTopMarkers(); - if (topMarkers != null) { - for (IMarker marker : topMarkers) { - String id = EclipseLintClient.getId(marker); - if (id != null && mExpandedIds.contains(id)) { - expanded.add(marker); - } - } - } - if (!expanded.isEmpty()) { - mTreeViewer.setExpandedElements(expanded.toArray()); - } - } - - if (mSelectedId != null) { - IMarker[] topMarkers = mContentProvider.getTopMarkers(); - for (IMarker marker : topMarkers) { - if (mSelectedId.equals(EclipseLintClient.getId(marker))) { - mTreeViewer.setSelection(new StructuredSelection(marker), true /*reveal*/); - break; - } - } - } - - return Status.OK_STATUS; - } - - @Override - public boolean shouldRun() { - // Do not run if the change came in before there is a viewer - return PlatformUI.isWorkbenchRunning(); - } - - @Override - public boolean belongsTo(Object family) { - return UPDATE_MARKERS_FAMILY == family; - } - } - - /** - * Returns the list of resources being shown in the list - * - * @return the list of resources being shown in this composite - */ - public List<? extends IResource> getResources() { - return mResources; - } - - /** Expands all nodes */ - public void expandAll() { - mTreeViewer.expandAll(); - - if (mExpandedIds == null) { - mExpandedIds = new HashSet<String>(); - } - IMarker[] topMarkers = mContentProvider.getTopMarkers(); - if (topMarkers != null) { - for (IMarker marker : topMarkers) { - String id = EclipseLintClient.getId(marker); - if (id != null) { - mExpandedIds.add(id); - } - } - } - } - - /** Collapses all nodes */ - public void collapseAll() { - mTreeViewer.collapseAll(); - mExpandedIds = null; - } - - // ---- Column Persistence ---- - - public void saveState(IMemento memento) { - if (mSingleFile) { - // Don't use persistence for single-file lists: this is a special mode of the - // window where we show a hardcoded set of columns for a single file, deliberately - // omitting the location column etc - return; - } - - IMemento columnEntry = memento.createChild(KEY_WIDTHS); - LintColumn[] columns = new LintColumn[mTree.getColumnCount()]; - int[] positions = mTree.getColumnOrder(); - for (int i = 0; i < columns.length; i++) { - TreeColumn treeColumn = mTree.getColumn(i); - LintColumn column = (LintColumn) treeColumn.getData(KEY_COLUMN); - // Workaround for TeeColumn.getWidth() returning 0 in some cases, - // see https://bugs.eclipse.org/341865 for details. - int width = getColumnWidth(column, mTreePainted); - columnEntry.putInteger(getKey(treeColumn), width); - columns[positions[i]] = column; - } - - if (getVisibleColumns() != null) { - IMemento visibleEntry = memento.createChild(KEY_VISIBLE); - for (LintColumn column : getVisibleColumns()) { - visibleEntry.putBoolean(getKey(column), true); - } - } - } - - private void createColumns() { - LintColumn[] columns = getVisibleColumns(); - TableLayout layout = new TableLayout(); - - for (int i = 0; i < columns.length; i++) { - LintColumn column = columns[i]; - TreeViewerColumn viewerColumn = null; - TreeColumn treeColumn; - viewerColumn = new TreeViewerColumn(mTreeViewer, SWT.NONE); - treeColumn = viewerColumn.getColumn(); - treeColumn.setData(KEY_COLUMN, column); - treeColumn.setResizable(true); - treeColumn.addSelectionListener(getHeaderListener()); - if (!column.isLeftAligned()) { - treeColumn.setAlignment(SWT.RIGHT); - } - viewerColumn.setLabelProvider(new LintColumnLabelProvider(column)); - treeColumn.setText(column.getColumnHeaderText()); - treeColumn.setImage(column.getColumnHeaderImage()); - IMemento columnWidths = null; - if (mMemento != null && !mSingleFile) { - columnWidths = mMemento.getChild(KEY_WIDTHS); - } - int columnWidth = getColumnWidth(column, false); - if (columnWidths != null) { - columnWidths.putInteger(getKey(column), columnWidth); - } - if (i == 0) { - // The first column should use layout -weights- to get all the - // remaining room - layout.addColumnData(new ColumnWeightData(1, true)); - } else if (columnWidth < 0) { - int defaultColumnWidth = column.getPreferredWidth(); - layout.addColumnData(new ColumnPixelData(defaultColumnWidth, true, true)); - } else { - layout.addColumnData(new ColumnPixelData(columnWidth, true)); - } - } - mTreeViewer.getTree().setLayout(layout); - mTree.layout(true); - } - - private int getColumnWidth(LintColumn column, boolean getFromUi) { - Tree tree = mTreeViewer.getTree(); - if (getFromUi) { - TreeColumn[] columns = tree.getColumns(); - for (int i = 0; i < columns.length; i++) { - if (column.equals(columns[i].getData(KEY_COLUMN))) { - return columns[i].getWidth(); - } - } - } - int preferredWidth = -1; - if (mMemento != null && !mSingleFile) { - IMemento columnWidths = mMemento.getChild(KEY_WIDTHS); - if (columnWidths != null) { - Integer value = columnWidths.getInteger(getKey(column)); - // Make sure we get a useful value - if (value != null && value.intValue() >= 0) - preferredWidth = value.intValue(); - } - } - if (preferredWidth <= 0) { - preferredWidth = Math.max(column.getPreferredWidth(), 30); - } - return preferredWidth; - } - - private static String getKey(TreeColumn treeColumn) { - return getKey((LintColumn) treeColumn.getData(KEY_COLUMN)); - } - - private static String getKey(LintColumn column) { - return column.getClass().getSimpleName(); - } - - private LintColumn[] getVisibleColumns() { - if (mVisibleColumns == null) { - if (mSingleFile) { - // Special mode where we show just lint warnings for a single file: - // use a hardcoded list of columns, not including path/location etc but - // including line numbers (which are normally not shown by default). - mVisibleColumns = new LintColumn[] { - mMessageColumn, mLineColumn - }; - } else { - // Generate visible columns based on (a) previously saved window state, - // and (b) default window visible states provided by the columns themselves - List<LintColumn> list = new ArrayList<LintColumn>(); - IMemento visibleColumns = null; - if (mMemento != null) { - visibleColumns = mMemento.getChild(KEY_VISIBLE); - } - for (LintColumn column : mColumns) { - if (visibleColumns != null) { - Boolean b = visibleColumns.getBoolean(getKey(column)); - if (b != null && b.booleanValue()) { - list.add(column); - } - } else if (column.visibleByDefault()) { - list.add(column); - } - } - if (!list.contains(mMessageColumn)) { - list.add(0, mMessageColumn); - } - mVisibleColumns = list.toArray(new LintColumn[list.size()]); - } - } - - return mVisibleColumns; - } - - int getCount(IMarker marker) { - return mContentProvider.getCount(marker); - } - - Issue getIssue(String id) { - return mRegistry.getIssue(id); - } - - Issue getIssue(IMarker marker) { - String id = EclipseLintClient.getId(marker); - return mRegistry.getIssue(id); - } - - Severity getSeverity(Issue issue) { - return mConfiguration.getSeverity(issue); - } - - // ---- Choosing visible columns ---- - - public void configureColumns() { - ColumnDialog dialog = new ColumnDialog(getShell(), mColumns, getVisibleColumns()); - if (dialog.open() == Window.OK) { - mVisibleColumns = dialog.getSelectedColumns(); - // Clear out columns: Must recreate to set the right label provider etc - for (TreeColumn column : mTree.getColumns()) { - column.dispose(); - } - createColumns(); - mTreeViewer.setComparator(new TableComparator()); - setSortIndicators(); - mTreeViewer.refresh(); - } - } - - // ---- Table Sorting ---- - - private SelectionListener getHeaderListener() { - return new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - final TreeColumn treeColumn = (TreeColumn) e.widget; - final LintColumn column = (LintColumn) treeColumn.getData(KEY_COLUMN); - - try { - IWorkbenchSiteProgressService progressService = getProgressService(); - if (progressService == null) { - BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { - @Override - public void run() { - resortTable(treeColumn, column, - new NullProgressMonitor()); - } - }); - } else { - getProgressService().busyCursorWhile(new IRunnableWithProgress() { - @Override - public void run(IProgressMonitor monitor) { - resortTable(treeColumn, column, monitor); - } - }); - } - } catch (InvocationTargetException e1) { - AdtPlugin.log(e1, null); - } catch (InterruptedException e1) { - return; - } - } - - private void resortTable(final TreeColumn treeColumn, LintColumn column, - IProgressMonitor monitor) { - TableComparator sorter = getTableSorter(); - monitor.beginTask("Sorting", 100); - monitor.worked(10); - if (column.equals(sorter.getTopColumn())) { - sorter.reverseTopPriority(); - } else { - sorter.setTopPriority(column); - } - monitor.worked(15); - PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - mTreeViewer.refresh(); - updateDirectionIndicator(treeColumn); - } - }); - monitor.done(); - } - }; - } - - private void setSortIndicators() { - LintColumn top = getTableSorter().getTopColumn(); - TreeColumn[] columns = mTreeViewer.getTree().getColumns(); - for (int i = 0; i < columns.length; i++) { - TreeColumn column = columns[i]; - if (column.getData(KEY_COLUMN).equals(top)) { - updateDirectionIndicator(column); - return; - } - } - } - - private void updateDirectionIndicator(TreeColumn column) { - Tree tree = mTreeViewer.getTree(); - tree.setSortColumn(column); - if (getTableSorter().isAscending()) { - tree.setSortDirection(SWT.UP); - } else { - tree.setSortDirection(SWT.DOWN); - } - } - - private TableComparator getTableSorter() { - return (TableComparator) mTreeViewer.getComparator(); - } - - /** Comparator used to sort the {@link LintList} tree. - * <p> - * This code is simplified from similar code in - * org.eclipse.ui.views.markers.internal.TableComparator - */ - private class TableComparator extends ViewerComparator { - private int[] mPriorities; - private boolean[] mDirections; - private int[] mDefaultPriorities; - private boolean[] mDefaultDirections; - - private TableComparator() { - int[] defaultPriorities = new int[mColumns.length]; - for (int i = 0; i < defaultPriorities.length; i++) { - defaultPriorities[i] = i; - } - mPriorities = defaultPriorities; - - boolean[] directions = new boolean[mColumns.length]; - for (int i = 0; i < directions.length; i++) { - directions[i] = mColumns[i].isAscending(); - } - mDirections = directions; - - mDefaultPriorities = new int[defaultPriorities.length]; - System.arraycopy(defaultPriorities, 0, this.mDefaultPriorities, 0, - defaultPriorities.length); - mDefaultDirections = new boolean[directions.length]; - System.arraycopy(directions, 0, this.mDefaultDirections, 0, directions.length); - } - - private void resetState() { - System.arraycopy(mDefaultPriorities, 0, mPriorities, 0, mPriorities.length); - System.arraycopy(mDefaultDirections, 0, mDirections, 0, mDirections.length); - } - - private void reverseTopPriority() { - mDirections[mPriorities[0]] = !mDirections[mPriorities[0]]; - } - - private void setTopPriority(LintColumn property) { - for (int i = 0; i < mColumns.length; i++) { - if (mColumns[i].equals(property)) { - setTopPriority(i); - return; - } - } - } - - private void setTopPriority(int priority) { - if (priority < 0 || priority >= mPriorities.length) { - return; - } - int index = -1; - for (int i = 0; i < mPriorities.length; i++) { - if (mPriorities[i] == priority) { - index = i; - } - } - if (index == -1) { - resetState(); - return; - } - // shift the array - for (int i = index; i > 0; i--) { - mPriorities[i] = mPriorities[i - 1]; - } - mPriorities[0] = priority; - mDirections[priority] = mDefaultDirections[priority]; - } - - private boolean isAscending() { - return mDirections[mPriorities[0]]; - } - - private int getTopPriority() { - return mPriorities[0]; - } - - private LintColumn getTopColumn() { - return mColumns[getTopPriority()]; - } - - @Override - public int compare(Viewer viewer, Object e1, Object e2) { - return compare((IMarker) e1, (IMarker) e2, 0, true); - } - - private int compare(IMarker marker1, IMarker marker2, int depth, - boolean continueSearching) { - if (depth >= mPriorities.length) { - return 0; - } - int column = mPriorities[depth]; - LintColumn property = mColumns[column]; - int result = property.compare(marker1, marker2); - if (result == 0 && continueSearching) { - return compare(marker1, marker2, depth + 1, continueSearching); - } - return result * (mDirections[column] ? 1 : -1); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java deleted file mode 100644 index f88c3772c..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.TitleAreaDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPartSite; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -@SuppressWarnings("restriction") // WST DOM access -class LintListDialog extends TitleAreaDialog implements SelectionListener { - private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$ - private final IFile mFile; - private final IEditorPart mEditor; - private Button mFixButton; - private Button mIgnoreButton; - private Button mIgnoreAllButton; - private Button mShowButton; - private Text mDetailsText; - private Button mIgnoreTypeButton; - private LintList mList; - - LintListDialog( - @NonNull Shell parentShell, - @NonNull IFile file, - @Nullable IEditorPart editor) { - super(parentShell); - mFile = file; - mEditor = editor; - setHelpAvailable(false); - } - - @Override - protected void setShellStyle(int newShellStyle) { - // Allow resize - super.setShellStyle(newShellStyle | SWT.TITLE | SWT.MODELESS | SWT.RESIZE); - } - - @Override - public boolean close() { - mList.dispose(); - return super.close(); - } - - @Override - protected Control createContents(Composite parent) { - Control contents = super.createContents(parent); - setTitle("Lint Warnings in Layout"); - setMessage("Lint Errors found for the current layout:"); - setTitleImage(IconFactory.getInstance().getIcon(PROJECT_LOGO_LARGE)); - - return contents; - } - - @SuppressWarnings("unused") // SWT constructors have side effects, they are not unused - @Override - protected Control createDialogArea(Composite parent) { - Composite area = (Composite) super.createDialogArea(parent); - Composite container = new Composite(area, SWT.NONE); - container.setLayoutData(new GridData(GridData.FILL_BOTH)); - - container.setLayout(new GridLayout(2, false)); - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - IWorkbenchPartSite site = null; - if (page.getActivePart() != null) { - site = page.getActivePart().getSite(); - } - - mList = new LintList(site, container, null /*memento*/, true /*singleFile*/); - mList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 6)); - - mShowButton = new Button(container, SWT.NONE); - mShowButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - mShowButton.setText("Show"); - mShowButton.setToolTipText("Opens the editor to reveal the XML with the issue"); - mShowButton.addSelectionListener(this); - - mFixButton = new Button(container, SWT.NONE); - mFixButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - mFixButton.setText("Fix"); - mFixButton.setToolTipText("Automatically corrects the problem, if possible"); - mFixButton.setEnabled(false); - mFixButton.addSelectionListener(this); - - mIgnoreButton = new Button(container, SWT.NONE); - mIgnoreButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - mIgnoreButton.setText("Suppress Issue"); - mIgnoreButton.setToolTipText("Adds a special attribute in the layout to suppress this specific warning"); - mIgnoreButton.addSelectionListener(this); - - mIgnoreAllButton = new Button(container, SWT.NONE); - mIgnoreAllButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - mIgnoreAllButton.setText("Suppress in Layout"); - mIgnoreAllButton.setEnabled(mEditor instanceof AndroidXmlEditor); - mIgnoreAllButton.setToolTipText("Adds an attribute on the root element to suppress all issues of this type in this layout"); - mIgnoreAllButton.addSelectionListener(this); - - mIgnoreTypeButton = new Button(container, SWT.NONE); - mIgnoreTypeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - mIgnoreTypeButton.setText("Disable Issue Type"); - mIgnoreTypeButton.setToolTipText("Turns off checking for this type of error everywhere"); - mIgnoreTypeButton.addSelectionListener(this); - - new Label(container, SWT.NONE); - - mDetailsText = new Text(container, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP - | SWT.V_SCROLL | SWT.MULTI); - Display display = parent.getDisplay(); - mDetailsText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); - mDetailsText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); - GridData gdText = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); - gdText.heightHint = 80; - mDetailsText.setLayoutData(gdText); - - new Label(container, SWT.NONE); - - mList.addSelectionListener(this); - - mList.setResources(Collections.<IResource>singletonList(mFile)); - mList.selectFirst(); - if (mList.getSelectedMarkers().size() > 0) { - updateSelectionState(); - } - - return area; - } - - /** - * Create contents of the button bar. - */ - @Override - protected void createButtonsForButtonBar(Composite parent) { - createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); - } - - /** - * Return the initial size of the dialog. - */ - @Override - protected Point getInitialSize() { - return new Point(600, 400); - } - - private void selectMarker(IMarker marker) { - if (marker == null) { - mDetailsText.setText(""); //$NON-NLS-1$ - return; - } - - mDetailsText.setText(EclipseLintClient.describe(marker)); - } - - // ---- Implements SelectionListener ---- - - @Override - public void widgetSelected(SelectionEvent e) { - Object source = e.getSource(); - if (source == mList.getTreeViewer().getControl()) { - // Enable/disable buttons - updateSelectionState(); - } else if (source == mShowButton) { - List<IMarker> selection = mList.getSelectedMarkers(); - if (selection.size() > 0) { - EclipseLintClient.showMarker(selection.get(0)); - } - } else if (source == mFixButton) { - List<IMarker> selection = mList.getSelectedMarkers(); - for (IMarker marker : selection) { - List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), marker); - if (fixes == null) { - continue; - } - LintFix fix = fixes.get(0); - IEditorPart editor = AdtUtils.getActiveEditor(); - if (editor instanceof AndroidXmlEditor) { - IStructuredDocument doc = ((AndroidXmlEditor) editor).getStructuredDocument(); - fix.apply(doc); - if (fix.needsFocus()) { - close(); - } - } else { - AdtPlugin.log(IStatus.ERROR, "Did not find associated editor to apply fix"); - } - } - } else if (source == mIgnoreTypeButton) { - for (IMarker marker : mList.getSelectedMarkers()) { - String id = EclipseLintClient.getId(marker); - if (id != null) { - LintFixGenerator.suppressDetector(id, true, mFile, true /*all*/); - } - } - } else if (source == mIgnoreButton) { - for (IMarker marker : mList.getSelectedMarkers()) { - LintFixGenerator.addSuppressAnnotation(marker); - } - } else if (source == mIgnoreAllButton) { - Set<String> ids = new HashSet<String>(); - for (IMarker marker : mList.getSelectedMarkers()) { - String id = EclipseLintClient.getId(marker); - if (id != null && !ids.contains(id)) { - ids.add(id); - if (mEditor instanceof AndroidXmlEditor) { - AndroidXmlEditor editor = (AndroidXmlEditor) mEditor; - AddSuppressAttribute fix = AddSuppressAttribute.createFixForAll(editor, - marker, id); - if (fix != null) { - IStructuredDocument document = editor.getStructuredDocument(); - fix.apply(document); - } - } - } - } - mList.refresh(); - } - } - - private void updateSelectionState() { - List<IMarker> selection = mList.getSelectedMarkers(); - - if (selection.size() == 1) { - selectMarker(selection.get(0)); - } else { - selectMarker(null); - } - - boolean canFix = selection.size() > 0; - for (IMarker marker : selection) { - if (!LintFix.hasFix(EclipseLintClient.getId(marker))) { - canFix = false; - break; - } - - // Some fixes cannot be run in bulk - if (selection.size() > 1) { - List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), marker); - if (fixes == null || !fixes.get(0).isBulkCapable()) { - canFix = false; - break; - } - } - } - - mFixButton.setEnabled(canFix); - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - Object source = e.getSource(); - if (source == mList.getTreeViewer().getControl()) { - // Jump to editor - List<IMarker> selection = mList.getSelectedMarkers(); - if (selection.size() > 0) { - EclipseLintClient.showMarker(selection.get(0)); - close(); - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintViewPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintViewPart.java deleted file mode 100644 index 90b956e32..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintViewPart.java +++ /dev/null @@ -1,657 +0,0 @@ -/* - * 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 static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.DOT_XML; - -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.preferences.LintPreferencePage; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.tools.lint.detector.api.LintUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.jobs.IJobChangeEvent; -import org.eclipse.core.runtime.jobs.IJobChangeListener; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IStatusLineManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.preference.IPreferenceNode; -import org.eclipse.jface.preference.PreferenceDialog; -import org.eclipse.jface.preference.PreferenceManager; -import org.eclipse.jface.preference.PreferenceNode; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.Region; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IMemento; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewSite; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.editors.text.TextFileDocumentProvider; -import org.eclipse.ui.part.ViewPart; -import org.eclipse.ui.texteditor.IDocumentProvider; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Eclipse View which shows lint warnings for the current project - */ -public class LintViewPart extends ViewPart implements SelectionListener, IJobChangeListener { - /** The view id for this view part */ - public static final String ID = "com.android.ide.eclipse.adt.internal.lint.LintViewPart"; //$NON-NLS-1$ - private static final String QUICKFIX_DISABLED_ICON = "quickfix-disabled"; //$NON-NLS-1$ - private static final String QUICKFIX_ICON = "quickfix"; //$NON-NLS-1$ - private static final String REFRESH_ICON = "refresh"; //$NON-NLS-1$ - private static final String EXPAND_DISABLED_ICON = "expandall-disabled"; //$NON-NLS-1$ - private static final String EXPAND_ICON = "expandall"; //$NON-NLS-1$ - private static final String COLUMNS_ICON = "columns"; //$NON-NLS-1$ - private static final String OPTIONS_ICON = "options"; //$NON-NLS-1$ - private static final String IGNORE_THIS_ICON = "ignore-this"; //$NON-NLS-1$ - private static final String IGNORE_THIS_DISABLED_ICON = "ignore-this-disabled"; //$NON-NLS-1$ - private static final String IGNORE_FILE_ICON = "ignore-file"; //$NON-NLS-1$ - private static final String IGNORE_FILE_DISABLED_ICON = "ignore-file-disabled"; //$NON-NLS-1$ - private static final String IGNORE_PRJ_ICON = "ignore-project"; //$NON-NLS-1$ - private static final String IGNORE_PRJ_DISABLED_ICON = "ignore-project-disabled"; //$NON-NLS-1$ - private static final String IGNORE_ALL_ICON = "ignore-all"; //$NON-NLS-1$ - private static final String IGNORE_ALL_DISABLED_ICON = "ignore-all-disabled"; //$NON-NLS-1$ - private IMemento mMemento; - private LintList mLintView; - private Text mDetailsText; - private Label mErrorLabel; - private SashForm mSashForm; - private Action mFixAction; - private Action mRemoveAction; - private Action mIgnoreAction; - private Action mAlwaysIgnoreAction; - private Action mIgnoreFileAction; - private Action mIgnoreProjectAction; - private Action mRemoveAllAction; - private Action mRefreshAction; - private Action mExpandAll; - private Action mCollapseAll; - private Action mConfigureColumns; - private Action mOptions; - - /** - * Initial projects to show: this field is only briefly not null during the - * construction initiated by {@link #show(List)} - */ - private static List<? extends IResource> sInitialResources; - - /** - * Constructs a new {@link LintViewPart} - */ - public LintViewPart() { - } - - @Override - public void init(IViewSite site, IMemento memento) throws PartInitException { - super.init(site, memento); - mMemento = memento; - } - - @Override - public void saveState(IMemento memento) { - super.saveState(memento); - - mLintView.saveState(memento); - } - - @Override - public void dispose() { - if (mLintView != null) { - mLintView.dispose(); - mLintView = null; - } - super.dispose(); - } - - @Override - public void createPartControl(Composite parent) { - GridLayout gridLayout = new GridLayout(1, false); - gridLayout.verticalSpacing = 0; - gridLayout.marginWidth = 0; - gridLayout.marginHeight = 0; - parent.setLayout(gridLayout); - - mErrorLabel = new Label(parent, SWT.NONE); - mErrorLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1)); - - mSashForm = new SashForm(parent, SWT.NONE); - mSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - mLintView = new LintList(getSite(), mSashForm, mMemento, false /*singleFile*/); - - mDetailsText = new Text(mSashForm, - SWT.BORDER | SWT.READ_ONLY | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI); - Display display = parent.getDisplay(); - mDetailsText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); - mDetailsText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); - - mLintView.addSelectionListener(this); - mSashForm.setWeights(new int[] {8, 2}); - - createActions(); - initializeToolBar(); - - // If there are currently running jobs, listen for them such that we can update the - // button state - refreshStopIcon(); - - if (sInitialResources != null) { - mLintView.setResources(sInitialResources); - sInitialResources = null; - } else { - // No supplied context: show lint warnings for all projects - IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(null); - if (androidProjects.length > 0) { - List<IResource> projects = new ArrayList<IResource>(); - for (IJavaProject project : androidProjects) { - projects.add(project.getProject()); - } - mLintView.setResources(projects); - } - } - - updateIssueCount(); - } - - /** - * Create the actions. - */ - private void createActions() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - IconFactory iconFactory = IconFactory.getInstance(); - mFixAction = new LintViewAction("Fix", ACTION_FIX, - iconFactory.getImageDescriptor(QUICKFIX_ICON), - iconFactory.getImageDescriptor(QUICKFIX_DISABLED_ICON)); - - mIgnoreAction = new LintViewAction("Suppress this error with an annotation/attribute", - ACTION_IGNORE_THIS, - iconFactory.getImageDescriptor(IGNORE_THIS_ICON), - iconFactory.getImageDescriptor(IGNORE_THIS_DISABLED_ICON)); - mIgnoreFileAction = new LintViewAction("Ignore in this file", ACTION_IGNORE_FILE, - iconFactory.getImageDescriptor(IGNORE_FILE_ICON), - iconFactory.getImageDescriptor(IGNORE_FILE_DISABLED_ICON)); - mIgnoreProjectAction = new LintViewAction("Ignore in this project", ACTION_IGNORE_TYPE, - iconFactory.getImageDescriptor(IGNORE_PRJ_ICON), - iconFactory.getImageDescriptor(IGNORE_PRJ_DISABLED_ICON)); - mAlwaysIgnoreAction = new LintViewAction("Always Ignore", ACTION_IGNORE_ALL, - iconFactory.getImageDescriptor(IGNORE_ALL_ICON), - iconFactory.getImageDescriptor(IGNORE_ALL_DISABLED_ICON)); - - mRemoveAction = new LintViewAction("Remove", ACTION_REMOVE, - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVE), - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVE_DISABLED)); - mRemoveAllAction = new LintViewAction("Remove All", ACTION_REMOVE_ALL, - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVEALL), - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVEALL_DISABLED)); - mRefreshAction = new LintViewAction("Refresh (& Save Files)", ACTION_REFRESH, - iconFactory.getImageDescriptor(REFRESH_ICON), null); - mRemoveAllAction.setEnabled(true); - mCollapseAll = new LintViewAction("Collapse All", ACTION_COLLAPSE, - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL), - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL_DISABLED)); - mCollapseAll.setEnabled(true); - mExpandAll = new LintViewAction("Expand All", ACTION_EXPAND, - iconFactory.getImageDescriptor(EXPAND_ICON), - iconFactory.getImageDescriptor(EXPAND_DISABLED_ICON)); - mExpandAll.setEnabled(true); - - mConfigureColumns = new LintViewAction("Configure Columns...", ACTION_COLUMNS, - iconFactory.getImageDescriptor(COLUMNS_ICON), - null); - - mOptions = new LintViewAction("Options...", ACTION_OPTIONS, - iconFactory.getImageDescriptor(OPTIONS_ICON), - null); - - enableActions(Collections.<IMarker>emptyList(), false /*updateWidgets*/); - } - - /** - * Initialize the toolbar. - */ - private void initializeToolBar() { - IToolBarManager toolbarManager = getViewSite().getActionBars().getToolBarManager(); - toolbarManager.add(mRefreshAction); - toolbarManager.add(mFixAction); - toolbarManager.add(mIgnoreAction); - toolbarManager.add(mIgnoreFileAction); - toolbarManager.add(mIgnoreProjectAction); - toolbarManager.add(mAlwaysIgnoreAction); - toolbarManager.add(new Separator()); - toolbarManager.add(mRemoveAction); - toolbarManager.add(mRemoveAllAction); - toolbarManager.add(new Separator()); - toolbarManager.add(mExpandAll); - toolbarManager.add(mCollapseAll); - toolbarManager.add(mConfigureColumns); - toolbarManager.add(mOptions); - } - - @Override - public void setFocus() { - mLintView.setFocus(); - } - - /** - * Sets the resource associated with the lint view - * - * @param resources the associated resources - */ - public void setResources(List<? extends IResource> resources) { - mLintView.setResources(resources); - - // Refresh the stop/refresh icon status - refreshStopIcon(); - } - - private void refreshStopIcon() { - Job[] currentJobs = LintJob.getCurrentJobs(); - if (currentJobs.length > 0) { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - mRefreshAction.setImageDescriptor(sharedImages.getImageDescriptor( - ISharedImages.IMG_ELCL_STOP)); - for (Job job : currentJobs) { - job.addJobChangeListener(this); - } - } else { - mRefreshAction.setImageDescriptor( - IconFactory.getInstance().getImageDescriptor(REFRESH_ICON)); - - } - } - - // ---- Implements SelectionListener ---- - - @Override - public void widgetSelected(SelectionEvent e) { - List<IMarker> markers = mLintView.getSelectedMarkers(); - if (markers.size() != 1) { - mDetailsText.setText(""); //$NON-NLS-1$ - } else { - mDetailsText.setText(EclipseLintClient.describe(markers.get(0))); - } - - IStatusLineManager status = getViewSite().getActionBars().getStatusLineManager(); - status.setMessage(mDetailsText.getText()); - - updateIssueCount(); - - enableActions(markers, true /* updateWidgets */); - } - - private void enableActions(List<IMarker> markers, boolean updateWidgets) { - // Update enabled state of actions - boolean hasSelection = markers.size() > 0; - boolean canFix = hasSelection; - for (IMarker marker : markers) { - if (!LintFix.hasFix(EclipseLintClient.getId(marker))) { - canFix = false; - break; - } - - // Some fixes cannot be run in bulk - if (markers.size() > 1) { - List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), marker); - if (fixes == null || !fixes.get(0).isBulkCapable()) { - canFix = false; - break; - } - } - } - - boolean haveFile = false; - boolean isJavaOrXml = true; - for (IMarker marker : markers) { - IResource resource = marker.getResource(); - if (resource instanceof IFile || resource instanceof IFolder) { - haveFile = true; - String name = resource.getName(); - if (!LintUtils.endsWith(name, DOT_XML) && !LintUtils.endsWith(name, DOT_JAVA)) { - isJavaOrXml = false; - } - break; - } - } - - mFixAction.setEnabled(canFix); - mIgnoreAction.setEnabled(hasSelection && haveFile && isJavaOrXml); - mIgnoreFileAction.setEnabled(hasSelection && haveFile); - mIgnoreProjectAction.setEnabled(hasSelection); - mAlwaysIgnoreAction.setEnabled(hasSelection); - mRemoveAction.setEnabled(hasSelection); - - if (updateWidgets) { - getViewSite().getActionBars().getToolBarManager().update(false); - } - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - Object source = e.getSource(); - if (source == mLintView.getTreeViewer().getControl()) { - // Jump to editor - List<IMarker> selection = mLintView.getSelectedMarkers(); - if (selection.size() > 0) { - EclipseLintClient.showMarker(selection.get(0)); - } - } - } - - // --- Implements IJobChangeListener ---- - - @Override - public void done(IJobChangeEvent event) { - mRefreshAction.setImageDescriptor( - IconFactory.getInstance().getImageDescriptor(REFRESH_ICON)); - - if (!mLintView.isDisposed()) { - mLintView.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - if (!mLintView.isDisposed()) { - updateIssueCount(); - } - } - }); - } - } - - private void updateIssueCount() { - int errors = mLintView.getErrorCount(); - int warnings = mLintView.getWarningCount(); - mErrorLabel.setText(String.format("%1$d errors, %2$d warnings", errors, warnings)); - } - - @Override - public void aboutToRun(IJobChangeEvent event) { - } - - @Override - public void awake(IJobChangeEvent event) { - } - - @Override - public void running(IJobChangeEvent event) { - } - - @Override - public void scheduled(IJobChangeEvent event) { - } - - @Override - public void sleeping(IJobChangeEvent event) { - } - - // ---- Actions ---- - - private static final int ACTION_REFRESH = 1; - private static final int ACTION_FIX = 2; - private static final int ACTION_IGNORE_THIS = 3; - private static final int ACTION_IGNORE_FILE = 4; - private static final int ACTION_IGNORE_TYPE = 5; - private static final int ACTION_IGNORE_ALL = 6; - private static final int ACTION_REMOVE = 7; - private static final int ACTION_REMOVE_ALL = 8; - private static final int ACTION_COLLAPSE = 9; - private static final int ACTION_EXPAND = 10; - private static final int ACTION_COLUMNS = 11; - private static final int ACTION_OPTIONS = 12; - - private class LintViewAction extends Action { - - private final int mAction; - - private LintViewAction(String label, int action, - ImageDescriptor imageDesc, ImageDescriptor disabledImageDesc) { - super(label); - mAction = action; - setImageDescriptor(imageDesc); - if (disabledImageDesc != null) { - setDisabledImageDescriptor(disabledImageDesc); - } - } - - @Override - public void run() { - switch (mAction) { - case ACTION_REFRESH: { - IWorkbench workbench = PlatformUI.getWorkbench(); - if (workbench != null) { - workbench.saveAllEditors(false /*confirm*/); - } - - Job[] jobs = LintJob.getCurrentJobs(); - if (jobs.length > 0) { - EclipseLintRunner.cancelCurrentJobs(false); - } else { - List<? extends IResource> resources = mLintView.getResources(); - if (resources == null) { - return; - } - Job job = EclipseLintRunner.startLint(resources, null, null, - false /*fatalOnly*/, false /*show*/); - if (job != null && workbench != null) { - job.addJobChangeListener(LintViewPart.this); - ISharedImages sharedImages = workbench.getSharedImages(); - setImageDescriptor(sharedImages.getImageDescriptor( - ISharedImages.IMG_ELCL_STOP)); - } - } - break; - } - case ACTION_FIX: { - List<IMarker> markers = mLintView.getSelectedMarkers(); - for (IMarker marker : markers) { - List<LintFix> fixes = LintFix.getFixes(EclipseLintClient.getId(marker), - marker); - if (fixes == null) { - continue; - } - LintFix fix = fixes.get(0); - IResource resource = marker.getResource(); - if (fix.needsFocus() && resource instanceof IFile) { - IRegion region = null; - try { - int start = marker.getAttribute(IMarker.CHAR_START, -1); - int end = marker.getAttribute(IMarker.CHAR_END, -1); - if (start != -1) { - region = new Region(start, end - start); - } - AdtPlugin.openFile((IFile) resource, region); - } catch (PartInitException e) { - AdtPlugin.log(e, "Can't open file %1$s", resource); - } - } - IDocumentProvider provider = new TextFileDocumentProvider(); - try { - provider.connect(resource); - IDocument document = provider.getDocument(resource); - if (document != null) { - fix.apply(document); - if (!fix.needsFocus()) { - provider.saveDocument(new NullProgressMonitor(), resource, - document, true /*overwrite*/); - } - } - } catch (Exception e) { - AdtPlugin.log(e, "Did not find associated editor to apply fix: %1$s", - resource.getName()); - } finally { - provider.disconnect(resource); - } - } - break; - } - case ACTION_REMOVE: { - for (IMarker marker : mLintView.getSelectedMarkers()) { - try { - marker.delete(); - } catch (CoreException e) { - AdtPlugin.log(e, null); - } - } - break; - } - case ACTION_REMOVE_ALL: { - List<? extends IResource> resources = mLintView.getResources(); - if (resources != null) { - for (IResource resource : resources) { - EclipseLintClient.clearMarkers(resource); - } - } - break; - } - case ACTION_IGNORE_ALL: - assert false; - break; - case ACTION_IGNORE_TYPE: - case ACTION_IGNORE_FILE: { - boolean ignoreInFile = mAction == ACTION_IGNORE_FILE; - for (IMarker marker : mLintView.getSelectedMarkers()) { - String id = EclipseLintClient.getId(marker); - if (id != null) { - IResource resource = marker.getResource(); - LintFixGenerator.suppressDetector(id, true, - ignoreInFile ? resource : resource.getProject(), - ignoreInFile); - } - } - break; - } - case ACTION_IGNORE_THIS: { - for (IMarker marker : mLintView.getSelectedMarkers()) { - LintFixGenerator.addSuppressAnnotation(marker); - } - break; - } - case ACTION_COLLAPSE: { - mLintView.collapseAll(); - break; - } - case ACTION_EXPAND: { - mLintView.expandAll(); - break; - } - case ACTION_COLUMNS: { - mLintView.configureColumns(); - break; - } - case ACTION_OPTIONS: { - PreferenceManager manager = new PreferenceManager(); - - LintPreferencePage page = new LintPreferencePage(); - String title = "Default/Global Settings"; - page.setTitle(title); - IPreferenceNode node = new PreferenceNode(title, page); - manager.addToRoot(node); - - - List<? extends IResource> resources = mLintView.getResources(); - if (resources != null) { - Set<IProject> projects = new HashSet<IProject>(); - for (IResource resource : resources) { - projects.add(resource.getProject()); - } - if (projects.size() > 0) { - for (IProject project : projects) { - page = new LintPreferencePage(); - page.setTitle(String.format("Settings for %1$s", - project.getName())); - page.setElement(project); - node = new PreferenceNode(project.getName(), page); - manager.addToRoot(node); - } - } - } - - Shell shell = LintViewPart.this.getSite().getShell(); - PreferenceDialog dialog = new PreferenceDialog(shell, manager); - dialog.create(); - dialog.setSelectedNode(title); - dialog.open(); - break; - } - default: - assert false : mAction; - } - updateIssueCount(); - } - } - - /** - * Shows or reconfigures the LintView to show the lint warnings for the - * given project - * - * @param projects the projects to show lint warnings for - */ - public static void show(List<? extends IResource> projects) { - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (window != null) { - IWorkbenchPage page = window.getActivePage(); - if (page != null) { - try { - // Pass initial project context via static field read by constructor - sInitialResources = projects; - IViewPart view = page.showView(LintViewPart.ID, null, - IWorkbenchPage.VIEW_ACTIVATE); - if (sInitialResources != null && view instanceof LintViewPart) { - // The view must be showing already since the constructor was not - // run, so reconfigure the view instead - LintViewPart lintView = (LintViewPart) view; - lintView.setResources(projects); - } - } catch (PartInitException e) { - AdtPlugin.log(e, "Cannot open Lint View"); - } finally { - sInitialResources = null; - } - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ObsoleteLayoutParamsFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ObsoleteLayoutParamsFix.java deleted file mode 100644 index 9db551733..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ObsoleteLayoutParamsFix.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; - -@SuppressWarnings("restriction") // DOM model -final class ObsoleteLayoutParamsFix extends DocumentFix { - private ObsoleteLayoutParamsFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - public boolean isBulkCapable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - if (node instanceof Element) { - Element element = (Element) node; - NamedNodeMap attributes = element.getAttributes(); - for (int i = 0, n = attributes.getLength(); i < n; i++) { - Attr attribute = (Attr) attributes.item(i); - if (attribute instanceof IndexedRegion) { - IndexedRegion region = (IndexedRegion) attribute; - if (region.getStartOffset() == start) { - element.removeAttribute(attribute.getName()); - return; - } - } - } - } - } - - @Override - public String getDisplayString() { - return "Remove attribute"; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_ETOOL_DELETE); - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ProjectLintConfiguration.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ProjectLintConfiguration.java deleted file mode 100644 index 9e4ca1226..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/ProjectLintConfiguration.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.VisibleForTesting; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.tools.lint.client.api.Configuration; -import com.android.tools.lint.client.api.DefaultConfiguration; -import com.android.tools.lint.client.api.LintClient; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.Project; -import com.android.tools.lint.detector.api.Severity; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.QualifiedName; - -import java.io.File; - -/** Configuration for Lint in Eclipse projects */ -class ProjectLintConfiguration extends DefaultConfiguration { - private boolean mFatalOnly; - - private final static QualifiedName CONFIGURATION_NAME = new QualifiedName(AdtPlugin.PLUGIN_ID, - "lintconfig"); //$NON-NLS-1$ - - @VisibleForTesting - ProjectLintConfiguration(LintClient client, Project project, - Configuration parent, boolean fatalOnly) { - super(client, project, parent); - mFatalOnly = fatalOnly; - } - - private static ProjectLintConfiguration create(LintClient client, IProject project, - Configuration parent, boolean fatalOnly) { - File dir = AdtUtils.getAbsolutePath(project).toFile(); - Project lintProject = client.getProject(dir, dir); - return new ProjectLintConfiguration(client, lintProject, parent, fatalOnly); - } - - public static ProjectLintConfiguration get(LintClient client, IProject project, - boolean fatalOnly) { - // Don't cache fatal-only configurations: they're only used occasionally and typically - // not repeatedly - if (fatalOnly) { - return create(client, project, GlobalLintConfiguration.get(), true); - } - - ProjectLintConfiguration configuration = null; - try { - Object value = project.getSessionProperty(CONFIGURATION_NAME); - configuration = (ProjectLintConfiguration) value; - } catch (CoreException e) { - // Not a problem; we will just create a new one - } - if (configuration == null) { - configuration = create(client, project, GlobalLintConfiguration.get(), false); - try { - project.setSessionProperty(CONFIGURATION_NAME, configuration); - } catch (CoreException e) { - AdtPlugin.log(e, "Can't store lint configuration"); - } - } - return configuration; - } - - @Override - public @NonNull Severity getSeverity(@NonNull Issue issue) { - Severity severity = super.getSeverity(issue); - if (mFatalOnly && severity != Severity.FATAL) { - return Severity.IGNORE; - } - return severity; - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/RemoveUselessViewFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/RemoveUselessViewFix.java deleted file mode 100644 index 0e9f326bf..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/RemoveUselessViewFix.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; -import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.UnwrapRefactoring; -import com.android.tools.lint.checks.UselessViewDetector; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextSelection; -import org.eclipse.jface.text.TextSelection; -import org.eclipse.ltk.ui.refactoring.RefactoringWizard; -import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -@SuppressWarnings("restriction") // DOM model -final class RemoveUselessViewFix extends DocumentFix { - private RemoveUselessViewFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return isCancelable(); - } - - @Override - public boolean isCancelable() { - return mId.equals(mId.equals(UselessViewDetector.USELESS_PARENT.getId())); - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - if (node instanceof Element && node.getParentNode() instanceof Element) { - Element element = (Element) node; - Element parent = (Element) node.getParentNode(); - - if (mId.equals(UselessViewDetector.USELESS_LEAF.getId())) { - parent.removeChild(element); - } else { - assert mId.equals(UselessViewDetector.USELESS_PARENT.getId()); - // Invoke refactoring - LayoutEditorDelegate delegate = - LayoutEditorDelegate.fromEditor(AdtUtils.getActiveEditor()); - - if (delegate != null) { - IFile file = (IFile) mMarker.getResource(); - ITextSelection textSelection = new TextSelection(start, - end - start); - UnwrapRefactoring refactoring = - new UnwrapRefactoring(file, delegate, textSelection, null); - RefactoringWizard wizard = refactoring.createWizard(); - RefactoringWizardOpenOperation op = - new RefactoringWizardOpenOperation(wizard); - try { - IWorkbenchWindow window = PlatformUI.getWorkbench(). - getActiveWorkbenchWindow(); - op.run(window.getShell(), wizard.getDefaultPageTitle()); - } catch (InterruptedException e) { - } - } - } - } - } - - @Override - public String getDisplayString() { - return "Remove unnecessary view"; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_ETOOL_DELETE); - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/RunLintAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/RunLintAction.java deleted file mode 100644 index 1de903e23..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/RunLintAction.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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 static com.android.SdkConstants.DOT_XML; - -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.tools.lint.detector.api.LintUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.ui.JavaElementLabelProvider; -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.ActionContributionItem; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IMenuCreator; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Menu; -import org.eclipse.ui.IObjectActionDelegate; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.IWorkbenchWindowPulldownDelegate; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.texteditor.ITextEditor; - -import java.util.ArrayList; -import java.util.List; - -/** - * Action which runs Lint on the currently projects (and also provides a - * pulldown menu in the toolbar for selecting specifically which projects to - * check) - */ -public class RunLintAction implements IObjectActionDelegate, IMenuCreator, - IWorkbenchWindowPulldownDelegate { - - private ISelection mSelection; - private Menu mMenu; - - @Override - public void selectionChanged(IAction action, ISelection selection) { - mSelection = selection; - } - - @Override - public void run(IAction action) { - List<IProject> projects = getProjects(mSelection, true /* warn */); - - if (!projects.isEmpty()) { - EclipseLintRunner.startLint(projects, null, null, false /*fatalOnly*/, true /*show*/); - } - } - - /** Returns the Android project(s) to apply a lint run to. */ - static List<IProject> getProjects(ISelection selection, boolean warn) { - List<IProject> projects = AdtUtils.getSelectedProjects(selection); - - if (projects.isEmpty() && warn) { - MessageDialog.openWarning(AdtPlugin.getShell(), "Lint", - "Could not run Lint: Select an Android project first."); - } - - return projects; - } - - @Override - public void setActivePart(IAction action, IWorkbenchPart targetPart) { - } - - @Override - public void dispose() { - if (mMenu != null) { - mMenu.dispose(); - } - } - - @Override - public void init(IWorkbenchWindow window) { - } - - // ---- IMenuCreator ---- - - @Override - public Menu getMenu(Control parent) { - mMenu = new Menu(parent); - - IconFactory iconFactory = IconFactory.getInstance(); - ImageDescriptor allIcon = iconFactory.getImageDescriptor("lintrun"); //$NON-NLS-1$ - LintMenuAction allAction = new LintMenuAction("Check All Projects", allIcon, - ACTION_RUN, null); - - addAction(allAction); - addSeparator(); - IJavaProject[] projects = AdtUtils.getOpenAndroidProjects(); - ILabelProvider provider = new JavaElementLabelProvider( - JavaElementLabelProvider.SHOW_DEFAULT); - for (IJavaProject project : projects) { - IProject p = project.getProject(); - ImageDescriptor icon = ImageDescriptor.createFromImage(provider.getImage(p)); - String label = String.format("Check %1$s", p.getName()); - LintMenuAction projectAction = new LintMenuAction(label, icon, ACTION_RUN, p); - addAction(projectAction); - } - - ITextEditor textEditor = AdtUtils.getActiveTextEditor(); - if (textEditor != null) { - IFile file = AdtUtils.getActiveFile(); - // Currently only supported for XML files - if (file != null && LintUtils.endsWith(file.getName(), DOT_XML)) { - ImageDescriptor icon = ImageDescriptor.createFromImage(provider.getImage(file)); - IAction fileAction = new LintMenuAction("Check Current File", icon, ACTION_RUN, - file); - - addSeparator(); - addAction(fileAction); - } - } - - ISharedImages images = PlatformUI.getWorkbench().getSharedImages(); - ImageDescriptor clear = images.getImageDescriptor(ISharedImages.IMG_ELCL_REMOVEALL); - LintMenuAction clearAction = new LintMenuAction("Clear Lint Warnings", clear, ACTION_CLEAR, - null); - addSeparator(); - addAction(clearAction); - - LintMenuAction excludeAction = new LintMenuAction("Skip Library Project Dependencies", - allIcon, ACTION_TOGGLE_EXCLUDE, null); - addSeparator(); - addAction(excludeAction); - excludeAction.setChecked(AdtPrefs.getPrefs().getSkipLibrariesFromLint()); - - return mMenu; - } - - private void addAction(IAction action) { - ActionContributionItem item = new ActionContributionItem(action); - item.fill(mMenu, -1); - } - - private void addSeparator() { - new Separator().fill(mMenu, -1); - } - - @Override - public Menu getMenu(Menu parent) { - return null; - } - - private static final int ACTION_RUN = 1; - private static final int ACTION_CLEAR = 2; - private static final int ACTION_TOGGLE_EXCLUDE = 3; - - /** - * Actions in the pulldown context menu: run lint or clear lint markers on - * the given resource - */ - private static class LintMenuAction extends Action { - private final IResource mResource; - private final int mAction; - - /** - * Creates a new context menu action - * - * @param text the label - * @param descriptor the icon - * @param action the action to run: run lint, clear, or toggle exclude libraries - * @param resource the resource to check or clear markers for, where - * null means all projects - */ - private LintMenuAction(String text, ImageDescriptor descriptor, int action, - IResource resource) { - super(text, action == ACTION_TOGGLE_EXCLUDE ? AS_CHECK_BOX : AS_PUSH_BUTTON); - if (descriptor != null) { - setImageDescriptor(descriptor); - } - mAction = action; - mResource = resource; - } - - @Override - public void run() { - if (mAction == ACTION_TOGGLE_EXCLUDE) { - AdtPrefs prefs = AdtPrefs.getPrefs(); - prefs.setSkipLibrariesFromLint(!prefs.getSkipLibrariesFromLint()); - return; - } - List<IResource> resources = new ArrayList<IResource>(); - if (mResource == null) { - // All projects - IJavaProject[] open = AdtUtils.getOpenAndroidProjects(); - for (IJavaProject project : open) { - resources.add(project.getProject()); - } - } else { - resources.add(mResource); - } - EclipseLintRunner.cancelCurrentJobs(false); - if (mAction == ACTION_CLEAR) { - EclipseLintClient.clearMarkers(resources); - } else { - assert mAction == ACTION_RUN; - EclipseLintRunner.startLint(resources, null, null, false /*fatalOnly*/, - true /*show*/); - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java deleted file mode 100644 index ea73b9a72..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.ANDROID_URI; -import static com.android.SdkConstants.ATTR_ALLOW_BACKUP; -import static com.android.SdkConstants.ATTR_BASELINE_ALIGNED; -import static com.android.SdkConstants.ATTR_CONTENT_DESCRIPTION; -import static com.android.SdkConstants.ATTR_ID; -import static com.android.SdkConstants.ATTR_INPUT_TYPE; -import static com.android.SdkConstants.ATTR_PERMISSION; -import static com.android.SdkConstants.ATTR_TRANSLATABLE; -import static com.android.SdkConstants.NEW_ID_PREFIX; -import static com.android.SdkConstants.VALUE_FALSE; - -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; -import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils; -import com.android.tools.lint.checks.AccessibilityDetector; -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.SecurityDetector; -import com.android.tools.lint.checks.TextFieldDetector; -import com.android.tools.lint.checks.TranslationDetector; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.ui.IEditorPart; -import org.w3c.dom.Element; - -/** Shared fix class for various builtin attributes */ -final class SetAttributeFix extends SetPropertyFix { - private SetAttributeFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - protected String getAttribute() { - if (mId.equals(AccessibilityDetector.ISSUE.getId())) { - return ATTR_CONTENT_DESCRIPTION; - } else if (mId.equals(InefficientWeightDetector.BASELINE_WEIGHTS.getId())) { - return ATTR_BASELINE_ALIGNED; - } else if (mId.equals(SecurityDetector.EXPORTED_SERVICE.getId())) { - return ATTR_PERMISSION; - } else if (mId.equals(TextFieldDetector.ISSUE.getId())) { - return ATTR_INPUT_TYPE; - } else if (mId.equals(TranslationDetector.MISSING.getId())) { - return ATTR_TRANSLATABLE; - } else if (mId.equals(ManifestDetector.ALLOW_BACKUP.getId())) { - return ATTR_ALLOW_BACKUP; - } else if (mId.equals(MissingIdDetector.ISSUE.getId())) { - return ATTR_ID; - } else { - assert false : mId; - return ""; - } - } - - @Override - protected boolean isAndroidAttribute() { - if (mId.equals(TranslationDetector.MISSING.getId())) { - return false; - } - - return true; - } - - @Override - public String getDisplayString() { - if (mId.equals(AccessibilityDetector.ISSUE.getId())) { - return "Add content description attribute"; - } else if (mId.equals(InefficientWeightDetector.BASELINE_WEIGHTS.getId())) { - return "Set baseline attribute"; - } else if (mId.equals(TextFieldDetector.ISSUE.getId())) { - return "Set input type"; - } else if (mId.equals(SecurityDetector.EXPORTED_SERVICE.getId())) { - return "Add permission attribute"; - } else if (mId.equals(TranslationDetector.MISSING.getId())) { - return "Mark this as a non-translatable resource"; - } else if (mId.equals(ManifestDetector.ALLOW_BACKUP.getId())) { - return "Set the allowBackup attribute to true or false"; - } else if (mId.equals(MissingIdDetector.ISSUE.getId())) { - return "Set the ID attribute"; - } else { - assert false : mId; - return ""; - } - } - - @Override - public String getAdditionalProposalInfo() { - String help = super.getAdditionalProposalInfo(); - - if (mId.equals(TranslationDetector.MISSING.getId())) { - help = "<b>Adds translatable=\"false\" to this <string>.</b><br><br>" + help; - } - - return help; - } - - @Override - protected boolean invokeCodeCompletion() { - return mId.equals(SecurityDetector.EXPORTED_SERVICE.getId()) - || mId.equals(TextFieldDetector.ISSUE.getId()) - || mId.equals(ManifestDetector.ALLOW_BACKUP.getId()); - } - - @Override - public boolean selectValue() { - if (mId.equals(TranslationDetector.MISSING.getId())) { - return false; - } else { - return super.selectValue(); - } - } - - @Override - protected String getProposal(Element element) { - if (mId.equals(InefficientWeightDetector.BASELINE_WEIGHTS.getId())) { - return VALUE_FALSE; - } else if (mId.equals(TranslationDetector.MISSING.getId())) { - return VALUE_FALSE; - } else if (mId.equals(TextFieldDetector.ISSUE.getId())) { - return element.getAttributeNS(ANDROID_URI, ATTR_INPUT_TYPE); - } else if (mId.equals(MissingIdDetector.ISSUE.getId())) { - IEditorPart editor = AdtUtils.getActiveEditor(); - if (editor instanceof AndroidXmlEditor) { - AndroidXmlEditor xmlEditor = (AndroidXmlEditor) editor; - return DescriptorsUtils.getFreeWidgetId(xmlEditor.getUiRootNode(), - "fragment"); //$NON-NLS-1$ - } else { - return NEW_ID_PREFIX; - } - } - - return super.getProposal(element); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java deleted file mode 100644 index a2b79c3c8..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.ANDROID_URI; - -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.utils.XmlUtils; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.Region; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -@SuppressWarnings("restriction") // DOM model -abstract class SetPropertyFix extends DocumentFix { - private Region mSelect; - - protected SetPropertyFix(String id, IMarker marker) { - super(id, marker); - } - - /** Attribute to be added */ - protected abstract String getAttribute(); - - /** Whether it's in the android: namespace */ - protected abstract boolean isAndroidAttribute(); - - protected String getProposal(Element element) { - return invokeCodeCompletion() ? "" : "TODO"; //$NON-NLS-1$ - } - - protected boolean invokeCodeCompletion() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - mSelect = null; - - if (node instanceof Element) { - Element element = (Element) node; - String proposal = getProposal(element); - String localAttribute = getAttribute(); - String prefix = null; - if (isAndroidAttribute()) { - prefix = XmlUtils.lookupNamespacePrefix(node, ANDROID_URI); - } - String attribute = prefix != null ? prefix + ':' + localAttribute : localAttribute; - - // This does not work even though it should: it does not include the prefix - //element.setAttributeNS(ANDROID_URI, localAttribute, proposal); - // So workaround instead: - element.setAttribute(attribute, proposal); - - Attr attr = null; - if (isAndroidAttribute()) { - attr = element.getAttributeNodeNS(ANDROID_URI, localAttribute); - } else { - attr = element.getAttributeNode(localAttribute); - } - if (attr instanceof IndexedRegion) { - IndexedRegion region = (IndexedRegion) attr; - int offset = region.getStartOffset(); - // We only want to select the value part inside the quotes, - // so skip the attribute and =" parts added by WST: - offset += attribute.length() + 2; - if (selectValue()) { - mSelect = new Region(offset, proposal.length()); - } - } - } - } - - protected boolean selectValue() { - return true; - } - - @Override - public void apply(IDocument document) { - try { - IFile file = (IFile) mMarker.getResource(); - super.apply(document); - AdtPlugin.openFile(file, mSelect, true); - } catch (PartInitException e) { - AdtPlugin.log(e, null); - } - - // Invoke code assist - if (invokeCodeCompletion()) { - IEditorPart editor = AdtUtils.getActiveEditor(); - if (editor instanceof AndroidXmlEditor) { - ((AndroidXmlEditor) editor).invokeContentAssist(-1); - } - } - } - - @Override - public boolean needsFocus() { - // Because we need to show the editor with text selected - return true; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - return sharedImages.getImage(ISharedImages.IMG_OBJ_ADD); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetScrollViewSizeFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetScrollViewSizeFix.java deleted file mode 100644 index 52860cf85..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetScrollViewSizeFix.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.ANDROID_URI; -import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT; -import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH; -import static com.android.SdkConstants.HORIZONTAL_SCROLL_VIEW; -import static com.android.SdkConstants.VALUE_WRAP_CONTENT; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -@SuppressWarnings("restriction") // DOM model -final class SetScrollViewSizeFix extends DocumentFix { - private SetScrollViewSizeFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - if (node instanceof Element && node.getParentNode() instanceof Element) { - Element element = (Element) node; - Element parent = (Element) node.getParentNode(); - - boolean isHorizontal = HORIZONTAL_SCROLL_VIEW.equals(parent.getTagName()); - String attributeName = isHorizontal ? ATTR_LAYOUT_WIDTH : ATTR_LAYOUT_HEIGHT; - element.setAttributeNS(ANDROID_URI, attributeName, VALUE_WRAP_CONTENT); - } - } - - @Override - public String getDisplayString() { - return "Replace size attribute with wrap_content"; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - // TODO: Need a better icon here - return sharedImages.getImage(ISharedImages.IMG_OBJ_ELEMENT); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java deleted file mode 100644 index 7cc05d203..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtPlugin; -import com.android.tools.lint.checks.TypoDetector; -import com.android.tools.lint.detector.api.TextFormat; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.FindReplaceDocumentAdapter; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Node; - -import java.util.ArrayList; -import java.util.List; - -/** Quickfix for fixing typos */ -@SuppressWarnings("restriction") // DOM model -final class TypoFix extends DocumentFix { - private String mTypo; - private String mReplacement; - - private TypoFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public String getDisplayString() { - return String.format("Replace \"%1$s\" by \"%2$s\"", mTypo, mReplacement); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, - int start, int end) { - String message = mMarker.getAttribute(IMarker.MESSAGE, ""); - String typo = TypoDetector.getTypo(message, TextFormat.TEXT); - if (typo == null) { - return; - } - List<String> replacements = TypoDetector.getSuggestions(message, TextFormat.TEXT); - if (replacements == null || replacements.isEmpty()) { - return; - } - - try { - String current = document.get(start, end-start); - if (current.equals(typo)) { - document.replace(start, end - start, replacements.get(0)); - } else { - // The buffer has been edited; try to find the typo. - FindReplaceDocumentAdapter finder = new FindReplaceDocumentAdapter(document); - IRegion forward = finder.find(start, typo, true /*forward*/, true, true, false); - IRegion backward = finder.find(start, typo, false /*forward*/, true, true, false); - if (forward != null && backward != null) { - // Pick the closest one - int forwardDelta = forward.getOffset() - start; - int backwardDelta = start - backward.getOffset(); - if (forwardDelta < backwardDelta) { - start = forward.getOffset(); - } else { - start = backward.getOffset(); - } - } else if (forward != null) { - start = forward.getOffset(); - } else if (backward != null) { - start = backward.getOffset(); - } else { - return; - } - end = start + typo.length(); - document.replace(start, end - start, replacements.get(0)); - } - } catch (BadLocationException e) { - AdtPlugin.log(e, null); - } - } - - @Override - protected List<LintFix> getAllFixes() { - String message = mMarker.getAttribute(IMarker.MESSAGE, ""); - String typo = TypoDetector.getTypo(message, TextFormat.TEXT); - List<String> replacements = TypoDetector.getSuggestions(message, TextFormat.TEXT); - if (replacements != null && !replacements.isEmpty() && typo != null) { - List<LintFix> allFixes = new ArrayList<LintFix>(replacements.size()); - for (String replacement : replacements) { - TypoFix fix = new TypoFix(mId, mMarker); - fix.mTypo = typo; - fix.mReplacement = replacement; - allFixes.add(fix); - } - - return allFixes; - } - - return null; - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypographyFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypographyFix.java deleted file mode 100644 index 535e02350..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypographyFix.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtPlugin; -import com.android.tools.lint.checks.TypographyDetector; - -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.util.List; - -@SuppressWarnings("restriction") // DOM model -final class TypographyFix extends DocumentFix { - private TypographyFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - public boolean isBulkCapable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, int start, - int end) { - if (node instanceof Element) { - Element element = (Element) node; - // Find the text node which contains the character in question - NodeList childNodes = element.getChildNodes(); - for (int i = 0, n = childNodes.getLength(); i < n; i++) { - Node child = childNodes.item(i); - if (child.getNodeType() == Node.TEXT_NODE) { - IndexedRegion region = (IndexedRegion) child; - String message = mMarker.getAttribute(IMarker.MESSAGE, ""); - List<TypographyDetector.ReplaceEdit> edits = - TypographyDetector.getEdits(mId, message, child); - for (TypographyDetector.ReplaceEdit edit : edits) { - try { - document.replace(edit.offset + region.getStartOffset(), - edit.length, edit.replaceWith); - } catch (BadLocationException e) { - AdtPlugin.log(e, null); - } - } - } - } - } - } - - @Override - public String getDisplayString() { - return "Replace with suggested characters"; - } - - @Override - public Image getImage() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - // TODO: Need a better icon here - return sharedImages.getImage(ISharedImages.IMG_OBJ_ELEMENT); - } -}
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/UseCompoundDrawableDetectorFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/UseCompoundDrawableDetectorFix.java deleted file mode 100644 index bf3cc9ac0..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/UseCompoundDrawableDetectorFix.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; -import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.UseCompoundDrawableRefactoring; -import com.android.tools.lint.checks.UseCompoundDrawableDetector; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IMarker; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.ITextSelection; -import org.eclipse.jface.text.TextSelection; -import org.eclipse.ltk.ui.refactoring.RefactoringWizard; -import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; -import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.w3c.dom.Node; - -/** Quickfix for the {@link UseCompoundDrawableDetector} */ -@SuppressWarnings("restriction") // DOM model -class UseCompoundDrawableDetectorFix extends DocumentFix { - protected UseCompoundDrawableDetectorFix(String id, IMarker marker) { - super(id, marker); - } - - @Override - public String getDisplayString() { - return "Convert to a compound drawable"; - } - - @Override - public Image getImage() { - return AdtPlugin.getAndroidLogo(); - } - - @Override - public boolean needsFocus() { - return false; - } - - @Override - public boolean isCancelable() { - return false; - } - - @Override - public boolean isBulkCapable() { - return false; - } - - @Override - protected void apply(IDocument document, IStructuredModel model, Node node, - int start, int end) { - - // Invoke refactoring - LayoutEditorDelegate delegate = - LayoutEditorDelegate.fromEditor(AdtUtils.getActiveEditor()); - - if (delegate != null) { - IFile file = (IFile) mMarker.getResource(); - ITextSelection textSelection = new TextSelection(start, - end - start); - UseCompoundDrawableRefactoring refactoring = - new UseCompoundDrawableRefactoring(file, delegate, textSelection, null); - RefactoringWizard wizard = refactoring.createWizard(); - RefactoringWizardOpenOperation op = - new RefactoringWizardOpenOperation(wizard); - try { - IWorkbenchWindow window = PlatformUI.getWorkbench(). - getActiveWorkbenchWindow(); - op.run(window.getShell(), wizard.getDefaultPageTitle()); - } catch (InterruptedException e) { - } - } - } -} |