1a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye/* 2a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * Copyright (C) 2011 The Android Open Source Project 3a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 4a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * you may not use this file except in compliance with the License. 6a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * You may obtain a copy of the License at 7a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 8a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * http://www.eclipse.org/org/documents/epl-v10.php 9a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 10a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * Unless required by applicable law or agreed to in writing, software 11a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * distributed under the License is distributed on an "AS IS" BASIS, 12a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * See the License for the specific language governing permissions and 14a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * limitations under the License. 15a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye */ 16a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyepackage com.android.ide.eclipse.adt.internal.lint; 17a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 1812d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.DOT_JAR; 1912d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.DOT_XML; 201fb460987f7d832adf12290f41448d0c16a95972Siva Velusamyimport static com.android.SdkConstants.FD_NATIVE_LIBS; 21a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport static com.android.ide.eclipse.adt.AdtConstants.MARKER_LINT; 224ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbyeimport static com.android.ide.eclipse.adt.AdtUtils.workspacePathToFile; 23a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 245dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbyeimport com.android.annotations.NonNull; 255dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbyeimport com.android.annotations.Nullable; 26a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.ide.eclipse.adt.AdtPlugin; 27a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.ide.eclipse.adt.AdtUtils; 28e50549f54810c29bffc681e39d33158ab2a8f26eRaphaelimport com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; 295ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; 305dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbyeimport com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 31a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; 32b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbyeimport com.android.ide.eclipse.adt.internal.sdk.Sdk; 33b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbyeimport com.android.sdklib.IAndroidTarget; 34229581314076be1b6f82fe1efed2bd00da340899Tor Norbyeimport com.android.tools.lint.checks.BuiltinIssueRegistry; 35229581314076be1b6f82fe1efed2bd00da340899Tor Norbyeimport com.android.tools.lint.client.api.Configuration; 36229581314076be1b6f82fe1efed2bd00da340899Tor Norbyeimport com.android.tools.lint.client.api.IDomParser; 3714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport com.android.tools.lint.client.api.IJavaParser; 38229581314076be1b6f82fe1efed2bd00da340899Tor Norbyeimport com.android.tools.lint.client.api.IssueRegistry; 39229581314076be1b6f82fe1efed2bd00da340899Tor Norbyeimport com.android.tools.lint.client.api.LintClient; 40a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.tools.lint.detector.api.Context; 413ce45b249f898697ae82e8c6dd045966227f3438Tor Norbyeimport com.android.tools.lint.detector.api.DefaultPosition; 428853b3b92496c5734bbcb75499030bb51a060097Tor Norbyeimport com.android.tools.lint.detector.api.Detector; 43a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.tools.lint.detector.api.Issue; 4414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport com.android.tools.lint.detector.api.JavaContext; 450fe590d956435c3c6a2d4c802108f627b173a573Tor Norbyeimport com.android.tools.lint.detector.api.LintUtils; 46a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.tools.lint.detector.api.Location; 473ce45b249f898697ae82e8c6dd045966227f3438Tor Norbyeimport com.android.tools.lint.detector.api.Location.Handle; 48a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.tools.lint.detector.api.Position; 49229581314076be1b6f82fe1efed2bd00da340899Tor Norbyeimport com.android.tools.lint.detector.api.Project; 50a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport com.android.tools.lint.detector.api.Severity; 513ce45b249f898697ae82e8c6dd045966227f3438Tor Norbyeimport com.android.tools.lint.detector.api.XmlContext; 5285e4a1a9dd133abb879ec211ce8dd385004edf22Xavier Ducrohetimport com.android.utils.Pair; 531fb460987f7d832adf12290f41448d0c16a95972Siva Velusamyimport com.android.utils.SdkUtils; 544ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbyeimport com.google.common.collect.Maps; 55a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 56a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.core.resources.IFile; 57a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.core.resources.IMarker; 587b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbyeimport org.eclipse.core.resources.IProject; 59a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.core.resources.IResource; 60a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.core.runtime.CoreException; 61a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.core.runtime.IStatus; 624ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbyeimport org.eclipse.jdt.core.IClasspathEntry; 637b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbyeimport org.eclipse.jdt.core.IJavaProject; 644ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbyeimport org.eclipse.jdt.core.JavaCore; 6514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.CompilationResult; 6614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies; 6714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; 6814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.batch.CompilationUnit; 6914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 7014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.impl.CompilerOptions; 7114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.parser.Parser; 7214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.problem.AbortCompilation; 7314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; 7414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport org.eclipse.jdt.internal.compiler.problem.ProblemReporter; 75a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.jface.text.BadLocationException; 76a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.jface.text.IDocument; 777b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbyeimport org.eclipse.jface.text.IRegion; 78a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.swt.widgets.Shell; 79a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.ui.IEditorPart; 807b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbyeimport org.eclipse.ui.PartInitException; 81a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.ui.editors.text.TextFileDocumentProvider; 82b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbyeimport org.eclipse.ui.ide.IDE; 83a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.ui.texteditor.IDocumentProvider; 84a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.wst.sse.core.StructuredModelManager; 85a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.wst.sse.core.internal.provisional.IModelManager; 86a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; 87a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; 88a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; 89a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; 905ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbyeimport org.w3c.dom.Attr; 91a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.w3c.dom.Document; 92a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport org.w3c.dom.Node; 93a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 948853b3b92496c5734bbcb75499030bb51a060097Tor Norbyeimport java.io.File; 95a85107f7d763276a5a040cf68e2046ac54202015Tor Norbyeimport java.io.IOException; 964ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbyeimport java.util.ArrayList; 975ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbyeimport java.util.Collection; 984c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbyeimport java.util.Collections; 994c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbyeimport java.util.List; 1005ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbyeimport java.util.Map; 1015ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbyeimport java.util.WeakHashMap; 102a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 10314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport lombok.ast.ecj.EcjTreeConverter; 10414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport lombok.ast.grammar.ParseProblem; 10514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbyeimport lombok.ast.grammar.Source; 10614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 107a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye/** 108a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * Eclipse implementation for running lint on workspace files and projects. 109a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye */ 110a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye@SuppressWarnings("restriction") // DOM model 111229581314076be1b6f82fe1efed2bd00da340899Tor Norbyepublic class EclipseLintClient extends LintClient implements IDomParser { 112a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye static final String MARKER_CHECKID_PROPERTY = "checkid"; //$NON-NLS-1$ 113c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye private static final String MODEL_PROPERTY = "model"; //$NON-NLS-1$ 1144c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye private final List<? extends IResource> mResources; 115a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye private final IDocument mDocument; 116229581314076be1b6f82fe1efed2bd00da340899Tor Norbye private boolean mWasFatal; 117229581314076be1b6f82fe1efed2bd00da340899Tor Norbye private boolean mFatalOnly; 11814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye private EclipseJavaParser mJavaParser; 1195ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye private boolean mCollectNodes; 1205ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye private Map<Node, IMarker> mNodeMap; 121a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 122a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye /** 123229581314076be1b6f82fe1efed2bd00da340899Tor Norbye * Creates a new {@link EclipseLintClient}. 124a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 125a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * @param registry the associated detector registry 1264c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye * @param resources the associated resources (project, file or null) 127a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * @param document the associated document, or null if the {@code resource} 128a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * param is not a file 129229581314076be1b6f82fe1efed2bd00da340899Tor Norbye * @param fatalOnly whether only fatal issues should be reported (and therefore checked) 130a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye */ 1314c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye public EclipseLintClient(IssueRegistry registry, List<? extends IResource> resources, 1324c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye IDocument document, boolean fatalOnly) { 1334c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye mResources = resources; 134a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye mDocument = document; 135229581314076be1b6f82fe1efed2bd00da340899Tor Norbye mFatalOnly = fatalOnly; 136a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 137a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 1385ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye /** 1395ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * Returns true if lint should only check fatal issues 1405ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * 1415ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * @return true if lint should only check fatal issues 1425ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye */ 1435ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye public boolean isFatalOnly() { 1445ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye return mFatalOnly; 1455ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 1465ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye 1475ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye /** 1485ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * Sets whether the lint client should store associated XML nodes for each 1495ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * reported issue 1505ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * 1515ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * @param collectNodes if true, collect node positions for errors in XML 1525ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * files, retrievable via the {@link #getIssueForNode} method 1535ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye */ 1545ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye public void setCollectNodes(boolean collectNodes) { 1555ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye mCollectNodes = collectNodes; 1565ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 1575ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye 1585ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye /** 1595ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * Returns one of the issues for the given node (there could be more than one) 1605ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * 1615ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * @param node the node to look up lint issues for 1625ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * @return the marker for one of the issues found for the given node 1635ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye */ 1645ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye @Nullable 1655ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye public IMarker getIssueForNode(@NonNull UiViewElementNode node) { 1665ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (mNodeMap != null) { 1675ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye return mNodeMap.get(node.getXmlNode()); 1685ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 1695ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye 1705ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye return null; 1715ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 1725ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye 1735ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye /** 1745ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * Returns a collection of nodes that have one or more lint warnings 1755ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * associated with them (retrievable via 1765ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * {@link #getIssueForNode(UiViewElementNode)}) 1775ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * 1785ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * @return a collection of nodes, which should <b>not</b> be modified by the 1795ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * caller 1805ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye */ 1815ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye @Nullable 1825ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye public Collection<Node> getIssueNodes() { 1835ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (mNodeMap != null) { 1845ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye return mNodeMap.keySet(); 1855ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 1865ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye 1875ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye return null; 1885ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 1895ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye 190229581314076be1b6f82fe1efed2bd00da340899Tor Norbye // ----- Extends LintClient ----- 191a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 1928853b3b92496c5734bbcb75499030bb51a060097Tor Norbye @Override 1937e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void log(@NonNull Severity severity, @Nullable Throwable exception, 1947e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @Nullable String format, @Nullable Object... args) { 195a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (exception == null) { 196a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(IStatus.WARNING, format, args); 197a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } else { 198a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(exception, format, args); 199a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 200a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 201a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 2028853b3b92496c5734bbcb75499030bb51a060097Tor Norbye @Override 2033ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye public IDomParser getDomParser() { 204a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return this; 205a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 206a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 20714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye @Override 20814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye public IJavaParser getJavaParser() { 20914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye if (mJavaParser == null) { 21014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye mJavaParser = new EclipseJavaParser(); 21114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 21214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 21314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return mJavaParser; 21414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 21514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 216a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye // ----- Implements IDomParser ----- 2178853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 218ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 2197e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public Document parseXml(@NonNull XmlContext context) { 220a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye // Map File to IFile 221a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye IFile file = AdtUtils.fileToIFile(context.file); 222a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (file == null || !file.exists()) { 223a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye String path = context.file.getPath(); 224a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(IStatus.ERROR, "Can't find file %1$s in workspace", path); 225a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return null; 226a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 227a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 228a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye IStructuredModel model = null; 229a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye try { 230a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye IModelManager modelManager = StructuredModelManager.getModelManager(); 231ec0dfbb255330df32eaafb5d785af458ef9a660cTor Norbye if (modelManager == null) { 232ec0dfbb255330df32eaafb5d785af458ef9a660cTor Norbye // This can happen if incremental lint is running right as Eclipse is shutting down 233ec0dfbb255330df32eaafb5d785af458ef9a660cTor Norbye return null; 234ec0dfbb255330df32eaafb5d785af458ef9a660cTor Norbye } 235a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye model = modelManager.getModelForRead(file); 236a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (model instanceof IDOMModel) { 237c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye context.setProperty(MODEL_PROPERTY, model); 238a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye IDOMModel domModel = (IDOMModel) model; 239a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return domModel.getDocument(); 240a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 241a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } catch (IOException e) { 242a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(e, "Cannot read XML file"); 243a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } catch (CoreException e) { 244a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(e, null); 245a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 246a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 247a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return null; 248a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 249a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 2504ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // Cache for {@link getProject} 2514ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye private IProject mLastEclipseProject; 2524ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye private Project mLastLintProject; 2534ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 2544c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye private IProject getProject(Project project) { 2554ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (project == mLastLintProject) { 2564ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye return mLastEclipseProject; 2574ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 2584ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 2594ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye mLastLintProject = project; 2604ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye mLastEclipseProject = null; 2614ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 2624c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye if (mResources != null) { 2634c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye if (mResources.size() == 1) { 2644ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye IProject p = mResources.get(0).getProject(); 2654ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye mLastEclipseProject = p; 2664ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye return p; 2674c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 2684c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye 2694ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye IProject last = null; 2704c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye for (IResource resource : mResources) { 2714c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye IProject p = resource.getProject(); 2724ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (p != last) { 2734ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (project.getDir().equals(AdtUtils.getAbsolutePath(p).toFile())) { 2744ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye mLastEclipseProject = p; 2754ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye return p; 2764ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 2774ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye last = p; 2784c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 2794c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 2804c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 2814ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 2824c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye return null; 2834c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 2844c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye 2855ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye @NonNull 2868853b3b92496c5734bbcb75499030bb51a060097Tor Norbye @Override 2877e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public Configuration getConfiguration(@NonNull Project project) { 2887e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye return getConfigurationFor(project); 2897e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye } 2907e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye 2917e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye /** 2927e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye * Same as {@link #getConfiguration(Project)}, but {@code project} can be 2937e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye * null in which case the global configuration is returned. 2947e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye * 2957e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye * @param project the project to look up 2967e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye * @return a corresponding configuration 2977e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye */ 2987e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @NonNull 2997e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public Configuration getConfigurationFor(@Nullable Project project) { 300105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye if (project != null) { 301105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye IProject eclipseProject = getProject(project); 302105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye if (eclipseProject != null) { 303105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye return ProjectLintConfiguration.get(this, eclipseProject, mFatalOnly); 304a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 305a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 306105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye 307105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye return GlobalLintConfiguration.get(); 308a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 3098853b3b92496c5734bbcb75499030bb51a060097Tor Norbye @Override 3107e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void report(@NonNull Context context, @NonNull Issue issue, @NonNull Severity s, 3117e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @Nullable Location location, 3127e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @NonNull String message, @Nullable Object data) { 313a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye int severity = getMarkerSeverity(s); 314a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye IMarker marker = null; 315402af1286193f536946b36979b259511d6a9bb06Tor Norbye if (location != null) { 316a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye Position startPosition = location.getStart(); 317a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (startPosition == null) { 3188853b3b92496c5734bbcb75499030bb51a060097Tor Norbye if (location.getFile() != null) { 319402af1286193f536946b36979b259511d6a9bb06Tor Norbye IResource resource = AdtUtils.fileToResource(location.getFile()); 320402af1286193f536946b36979b259511d6a9bb06Tor Norbye if (resource != null && resource.isAccessible()) { 321402af1286193f536946b36979b259511d6a9bb06Tor Norbye marker = BaseProjectHelper.markResource(resource, MARKER_LINT, 322402af1286193f536946b36979b259511d6a9bb06Tor Norbye message, 0, severity); 323402af1286193f536946b36979b259511d6a9bb06Tor Norbye } 3248853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 325a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } else { 326a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye Position endPosition = location.getEnd(); 327a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye int line = startPosition.getLine() + 1; // Marker API is 1-based 328a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye IFile file = AdtUtils.fileToIFile(location.getFile()); 329402af1286193f536946b36979b259511d6a9bb06Tor Norbye if (file != null && file.isAccessible()) { 330a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye Pair<Integer, Integer> r = getRange(file, mDocument, 331a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye startPosition, endPosition); 332a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye int startOffset = r.getFirst(); 333a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye int endOffset = r.getSecond(); 334a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye marker = BaseProjectHelper.markResource(file, MARKER_LINT, 335a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye message, line, startOffset, endOffset, severity); 336a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 337a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 338a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 339a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 340402af1286193f536946b36979b259511d6a9bb06Tor Norbye if (marker == null) { 3414c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye marker = BaseProjectHelper.markResource(mResources.get(0), MARKER_LINT, 342402af1286193f536946b36979b259511d6a9bb06Tor Norbye message, 0, severity); 343402af1286193f536946b36979b259511d6a9bb06Tor Norbye } 344402af1286193f536946b36979b259511d6a9bb06Tor Norbye 345a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (marker != null) { 346a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye // Store marker id such that we can recognize it from the suppress quickfix 347a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye try { 348a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye marker.setAttribute(MARKER_CHECKID_PROPERTY, issue.getId()); 349a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } catch (CoreException e) { 350a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(e, null); 351a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 352a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 353a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 3545da3610b249d74267a67a6b48acdf4cc95475bc0Tor Norbye if (s == Severity.FATAL) { 355229581314076be1b6f82fe1efed2bd00da340899Tor Norbye mWasFatal = true; 356a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 3575ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye 3585ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (mCollectNodes && location != null && marker != null) { 3595ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (location instanceof LazyLocation) { 3605ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye LazyLocation l = (LazyLocation) location; 3615ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye IndexedRegion region = l.mRegion; 3625ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (region instanceof Node) { 3635ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye Node node = (Node) region; 3645ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (node instanceof Attr) { 3655ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye node = ((Attr) node).getOwnerElement(); 3665ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 3675ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (mNodeMap == null) { 3685ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye mNodeMap = new WeakHashMap<Node, IMarker>(); 3695ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 3705ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye IMarker prev = mNodeMap.get(node); 3715ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (prev != null) { 3725ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye // Only replace the node if this node has higher priority 3735ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye int prevSeverity = prev.getAttribute(IMarker.SEVERITY, 0); 3745ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye if (prevSeverity < severity) { 3755ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye mNodeMap.put(node, marker); 3765ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 3775ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } else { 3785ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye mNodeMap.put(node, marker); 3795ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 3805ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 3815ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 3825ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye } 383a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 384a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 3855dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye @Override 3865dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye @Nullable 3875dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye public File findResource(@NonNull String relativePath) { 388cb3bddedd22155d23f741e764168174c3e223807Tor Norbye // Look within the $ANDROID_SDK 3895dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye String sdkFolder = AdtPrefs.getPrefs().getOsSdkFolder(); 3905dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye if (sdkFolder != null) { 391cb3bddedd22155d23f741e764168174c3e223807Tor Norbye File file = new File(sdkFolder, relativePath); 3925dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye if (file.exists()) { 3935dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye return file; 3945dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye } 3955dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye } 3965dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye 3975dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye return null; 3985dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye } 3995dc20a5c893caa37deff6b2f9f928e571027a137Tor Norbye 4009105cd9318152b97845ad0255d921e7921715deaTor Norbye /** 4019105cd9318152b97845ad0255d921e7921715deaTor Norbye * Clears any lint markers from the given resource (project, folder or file) 4029105cd9318152b97845ad0255d921e7921715deaTor Norbye * 4039105cd9318152b97845ad0255d921e7921715deaTor Norbye * @param resource the resource to remove markers from 4049105cd9318152b97845ad0255d921e7921715deaTor Norbye */ 4059105cd9318152b97845ad0255d921e7921715deaTor Norbye public static void clearMarkers(@NonNull IResource resource) { 4064c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye clearMarkers(Collections.singletonList(resource)); 4074c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 4084c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye 4094c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye /** Clears any lint markers from the given list of resource (project, folder or file) */ 4104c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye static void clearMarkers(List<? extends IResource> resources) { 4114c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye for (IResource resource : resources) { 4124c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye try { 4134c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye if (resource.isAccessible()) { 4144c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye resource.deleteMarkers(MARKER_LINT, false, IResource.DEPTH_INFINITE); 4154c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 4164c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } catch (CoreException e) { 4174c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye AdtPlugin.log(e, null); 4184c68f3dc9f10b76f1a32ff9c86587adca385a6d7Tor Norbye } 419a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 420a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 4217e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye IEditorPart activeEditor = AdtUtils.getActiveEditor(); 4227e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(activeEditor); 423e50549f54810c29bffc681e39d33158ab2a8f26eRaphael if (delegate != null) { 424e50549f54810c29bffc681e39d33158ab2a8f26eRaphael delegate.getGraphicalEditor().getLayoutActionBar().updateErrorIndicator(); 425a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 426a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 427a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 428a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye /** 4297b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * Removes all markers of the given id from the given resource. 4307b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * 4317b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * @param resource the resource to remove markers from (file or project, or 4327b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * null for all open projects) 4337b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * @param id the id for the issue whose markers should be deleted 4347b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye */ 4357b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye public static void removeMarkers(IResource resource, String id) { 4367b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye if (resource == null) { 4377b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye IJavaProject[] androidProjects = BaseProjectHelper.getAndroidProjects(null); 4387b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye for (IJavaProject project : androidProjects) { 4397b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye IProject p = project.getProject(); 4407b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye if (p != null) { 4417b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye // Recurse, but with a different parameter so it will not continue recursing 4427b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye removeMarkers(p, id); 4437b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 4447b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 4457b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye return; 4467b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 4477b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye IMarker[] markers = getMarkers(resource); 4487b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye for (IMarker marker : markers) { 4497b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye if (id.equals(getId(marker))) { 4507b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye try { 4517b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye marker.delete(); 4527b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } catch (CoreException e) { 4537b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye AdtPlugin.log(e, null); 4547b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 4557b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 4567b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 4577b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 4587b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 4597b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye /** 460a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * Returns the lint marker for the given resource (which may be a project, folder or file) 461a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 462a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * @param resource the resource to be checked, typically a source file 463a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * @return an array of markers, possibly empty but never null 464a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye */ 465a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye public static IMarker[] getMarkers(IResource resource) { 466a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye try { 467402af1286193f536946b36979b259511d6a9bb06Tor Norbye if (resource.isAccessible()) { 468402af1286193f536946b36979b259511d6a9bb06Tor Norbye return resource.findMarkers(MARKER_LINT, false, IResource.DEPTH_INFINITE); 469402af1286193f536946b36979b259511d6a9bb06Tor Norbye } 470a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } catch (CoreException e) { 471a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(e, null); 472a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 473a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 474a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return new IMarker[0]; 475a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 476a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 477a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye private static int getMarkerSeverity(Severity severity) { 478a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye switch (severity) { 479a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye case INFORMATIONAL: 480a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return IMarker.SEVERITY_INFO; 481a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye case WARNING: 482a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return IMarker.SEVERITY_WARNING; 4835da3610b249d74267a67a6b48acdf4cc95475bc0Tor Norbye case FATAL: 484a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye case ERROR: 485a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye default: 486a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return IMarker.SEVERITY_ERROR; 487a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 488a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 489a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 490a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye private static Pair<Integer, Integer> getRange(IFile file, IDocument doc, 491a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye Position startPosition, Position endPosition) { 492a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye int startOffset = startPosition.getOffset(); 493a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye int endOffset = endPosition != null ? endPosition.getOffset() : -1; 494a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (endOffset != -1) { 495a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye // Attribute ranges often include trailing whitespace; trim this up 496a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (doc == null) { 497a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye IDocumentProvider provider = new TextFileDocumentProvider(); 498a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye try { 499a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye provider.connect(file); 500a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye doc = provider.getDocument(file); 501a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (doc != null) { 502b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye return adjustOffsets(doc, startOffset, endOffset); 503a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 504a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } catch (Exception e) { 505a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye AdtPlugin.log(e, "Can't find range information for %1$s", file.getName()); 506a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } finally { 507a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye provider.disconnect(file); 508a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 509a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } else { 510b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye return adjustOffsets(doc, startOffset, endOffset); 511a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 512a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 513a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 514a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return Pair.of(startOffset, startOffset); 515a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 516a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 517b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye /** 518b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * Trim off any trailing space on the given offset range in the given 519b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * document, and don't span multiple lines on ranges since it makes (for 520b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * example) the XML editor just glow with yellow underlines for all the 521b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * attributes etc. Highlighting just the element beginning gets the point 522b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * across. It also makes it more obvious where there are warnings on both 523b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * the overall element and on individual attributes since without this the 524b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * warnings on attributes would just overlap with the whole-element 525b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye * highlighting. 526b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye */ 527b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye private static Pair<Integer, Integer> adjustOffsets(IDocument doc, int startOffset, 528a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye int endOffset) { 529a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (doc != null) { 530a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye while (endOffset > startOffset && endOffset < doc.getLength()) { 531a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye try { 532a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye if (!Character.isWhitespace(doc.getChar(endOffset - 1))) { 533a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye break; 534a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } else { 535a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye endOffset--; 536a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 537a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } catch (BadLocationException e) { 538a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye // Pass - we've already validated offset range above 539a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye break; 540a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 541a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 542b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye 543b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye // Also don't span lines 544b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye int lineEnd = startOffset; 545b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye while (lineEnd < endOffset) { 546b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye try { 547b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye char c = doc.getChar(lineEnd); 548b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye if (c == '\n' || c == '\r') { 549b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye endOffset = lineEnd; 550b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye break; 551b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye } 552b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye } catch (BadLocationException e) { 553b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye // Pass - we've already validated offset range above 554b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye break; 555b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye } 556b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye lineEnd++; 557b4622eb274f472919a7d7ae0bab045e4b9e4325fTor Norbye } 558a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 559a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 560a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye return Pair.of(startOffset, endOffset); 561a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 562a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 563a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye /** 564a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * Returns true if a fatal error was encountered 565a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 566a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * @return true if a fatal error was encountered 567a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye */ 568229581314076be1b6f82fe1efed2bd00da340899Tor Norbye public boolean hasFatalErrors() { 569229581314076be1b6f82fe1efed2bd00da340899Tor Norbye return mWasFatal; 570a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 571a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 572a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye /** 5737b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * Describe the issue for the given marker 5747b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * 5757b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * @param marker the marker to look up 5767b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * @return a full description of the corresponding issue, never null 5777b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye */ 5787b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye public static String describe(IMarker marker) { 579229581314076be1b6f82fe1efed2bd00da340899Tor Norbye IssueRegistry registry = getRegistry(); 580b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye String markerId = getId(marker); 581b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye Issue issue = registry.getIssue(markerId); 582b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye if (issue == null) { 583b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye return ""; 584b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye } 585b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye 5867b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye String summary = issue.getDescription(); 587addbd7110d87e9f48d854e5ba6a729359110ada8Tor Norbye String explanation = issue.getExplanationAsSimpleText(); 5887b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 5897b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye StringBuilder sb = new StringBuilder(summary.length() + explanation.length() + 20); 5907b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye try { 5917b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append((String) marker.getAttribute(IMarker.MESSAGE)); 5927b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append('\n').append('\n'); 5937b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } catch (CoreException e) { 5947b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 5957b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append("Issue: "); 5967b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append(summary); 597105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye sb.append('\n'); 598105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye sb.append("Id: "); 599105dc49ddd885c07b520dd343aa326c306d2c3deTor Norbye sb.append(issue.getId()); 6007b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append('\n').append('\n'); 6017b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append(explanation); 6027b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 6037b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye if (issue.getMoreInfo() != null) { 6047b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append('\n').append('\n'); 6057b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye sb.append(issue.getMoreInfo()); 6067b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6077b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 6087b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye return sb.toString(); 6097b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6107b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 6117b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye /** 6127b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * Returns the id for the given marker 6137b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * 6147b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * @param marker the marker to look up 6157b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * @return the corresponding issue id, or null 6167b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye */ 6177b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye public static String getId(IMarker marker) { 6187b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye try { 6197b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye return (String) marker.getAttribute(MARKER_CHECKID_PROPERTY); 6207b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } catch (CoreException e) { 6217b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye return null; 6227b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6237b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6247b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 6257b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye /** 6267b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * Shows the given marker in the editor 6277b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * 6287b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye * @param marker the marker to be shown 6297b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye */ 6307b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye public static void showMarker(IMarker marker) { 6317b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye IRegion region = null; 6327b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye try { 6337b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye int start = marker.getAttribute(IMarker.CHAR_START, -1); 6347b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye int end = marker.getAttribute(IMarker.CHAR_END, -1); 6357b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye if (start >= 0 && end >= 0) { 6367b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye region = new org.eclipse.jface.text.Region(start, end - start); 6377b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6387b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 6397b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye IResource resource = marker.getResource(); 6407b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye if (resource instanceof IFile) { 641b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye IEditorPart editor = 642b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye AdtPlugin.openFile((IFile) resource, region, true /* showEditorTab */); 643b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye if (editor != null) { 644b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye IDE.gotoMarker(editor, marker); 645b45957a134d6fd6184348387fd0f0b14ffa7021cTor Norbye } 6467b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6477b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } catch (PartInitException ex) { 6487b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye AdtPlugin.log(ex, null); 6497b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6507b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye } 6517b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye 6527b08b8258cffcb3085a90d32e02da95fafbfdeafTor Norbye /** 653a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * Show a dialog with errors for the given file 654a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 655a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * @param shell the parent shell to attach the dialog to 656a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * @param file the file to show the errors for 6575ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye * @param editor the editor for the file, if known 658a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye */ 6595ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye public static void showErrors( 6605ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye @NonNull Shell shell, 6615ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye @NonNull IFile file, 6625ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye @Nullable IEditorPart editor) { 6635ae903bf8670f40e9eb40ebbd0a25c15eaac5962Tor Norbye LintListDialog dialog = new LintListDialog(shell, file, editor); 664a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye dialog.open(); 665a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 666a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 6678853b3b92496c5734bbcb75499030bb51a060097Tor Norbye @Override 6687e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull String readFile(@NonNull File f) { 6698853b3b92496c5734bbcb75499030bb51a060097Tor Norbye // Map File to IFile 6708853b3b92496c5734bbcb75499030bb51a060097Tor Norbye IFile file = AdtUtils.fileToIFile(f); 6718853b3b92496c5734bbcb75499030bb51a060097Tor Norbye if (file == null || !file.exists()) { 6728853b3b92496c5734bbcb75499030bb51a060097Tor Norbye String path = f.getPath(); 6738853b3b92496c5734bbcb75499030bb51a060097Tor Norbye AdtPlugin.log(IStatus.ERROR, "Can't find file %1$s in workspace", path); 67423f0d6a5e0d332d7a29f8d320b9c33badfae9451Tor Norbye return readPlainFile(f); 6758853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 6768853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 6771fb460987f7d832adf12290f41448d0c16a95972Siva Velusamy if (SdkUtils.endsWithIgnoreCase(file.getName(), DOT_XML)) { 678e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye IStructuredModel model = null; 679e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye try { 680e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye IModelManager modelManager = StructuredModelManager.getModelManager(); 681e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye model = modelManager.getModelForRead(file); 682e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye return model.getStructuredDocument().get(); 683e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye } catch (IOException e) { 684e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye AdtPlugin.log(e, "Cannot read XML file"); 685e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye } catch (CoreException e) { 686e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye AdtPlugin.log(e, null); 687e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye } finally { 688e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye if (model != null) { 689e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye // TODO: This may be too early... 690e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye model.releaseFromRead(); 691e24afba79ef6ee7a298cee003355d40bcad5058eTor Norbye } 6928853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 6938853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 6948853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 6958853b3b92496c5734bbcb75499030bb51a060097Tor Norbye return readPlainFile(f); 6968853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 6978853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 698581ca2e75fd638f6e95570ac54ff9e6b7b7cde84Tor Norbye private String readPlainFile(File file) { 6998853b3b92496c5734bbcb75499030bb51a060097Tor Norbye try { 7008dcd0726088eee54368e032e7dc6b31a450b4ee1Tor Norbye return LintUtils.getEncodedString(this, file); 7018853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } catch (IOException e) { 702581ca2e75fd638f6e95570ac54ff9e6b7b7cde84Tor Norbye return ""; //$NON-NLS-1$ 7038853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 7048853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 7058853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 706ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 7077e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node) { 708c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); 709c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye return new LazyLocation(context.file, model.getStructuredDocument(), (IndexedRegion) node); 7103ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye } 7113ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye 712ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 7135e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye public @NonNull Location getLocation(@NonNull XmlContext context, @NonNull Node node, 7145e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye int start, int end) { 7155e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye IndexedRegion region = (IndexedRegion) node; 7165e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye int nodeStart = region.getStartOffset(); 7175e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye 7185e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); 7195e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye // Get line number 7205e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye LazyLocation location = new LazyLocation(context.file, model.getStructuredDocument(), 7215e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye region); 7225e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye int line = location.getStart().getLine(); 7235e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye 7245e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye Position startPos = new DefaultPosition(line, -1, nodeStart + start); 7255e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye Position endPos = new DefaultPosition(line, -1, nodeStart + end); 7265e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye return Location.create(context.file, startPos, endPos); 7275e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye } 7285e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye 7295e290ab6060c3204be3a3eb6084db6f92c88adeeTor Norbye @Override 7307e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Handle createLocationHandle(final @NonNull XmlContext context, 7317e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye final @NonNull Node node) { 732c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); 733c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye return new LazyLocation(context.file, model.getStructuredDocument(), (IndexedRegion) node); 7348853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 7358853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 7364ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye private Map<Project, ClassPathInfo> mProjectInfo; 7374ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 7384ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye @Override 7394ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye @NonNull 7404ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye protected ClassPathInfo getClassPath(@NonNull Project project) { 7414ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye ClassPathInfo info; 7424ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (mProjectInfo == null) { 7434ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye mProjectInfo = Maps.newHashMap(); 7444ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye info = null; 7454ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } else { 7464ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye info = mProjectInfo.get(project); 7474ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 7484ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 7494ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (info == null) { 7504ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye List<File> sources = null; 7514ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye List<File> classes = null; 7524ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye List<File> libraries = null; 7534ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 7544ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye IProject p = getProject(project); 7554ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (p != null) { 7564ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye try { 7574ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye IJavaProject javaProject = BaseProjectHelper.getJavaProject(p); 7584ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 7594ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // Output path 7604ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye File file = workspacePathToFile(javaProject.getOutputLocation()); 7614ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye classes = Collections.singletonList(file); 7624ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 7634ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // Source path 7644ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye IClasspathEntry[] entries = javaProject.getRawClasspath(); 7654ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye sources = new ArrayList<File>(entries.length); 7664ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye libraries = new ArrayList<File>(entries.length); 7674ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye for (int i = 0; i < entries.length; i++) { 7684ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye IClasspathEntry entry = entries[i]; 7694ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye int kind = entry.getEntryKind(); 7704ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 7714ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (kind == IClasspathEntry.CPE_VARIABLE) { 7724ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye entry = JavaCore.getResolvedClasspathEntry(entry); 773ea7dd912dc8f5b8f3ae8545166657beacb429552Tor Norbye if (entry == null) { 774ea7dd912dc8f5b8f3ae8545166657beacb429552Tor Norbye // It's possible that the variable is no longer valid; ignore 775ea7dd912dc8f5b8f3ae8545166657beacb429552Tor Norbye continue; 776ea7dd912dc8f5b8f3ae8545166657beacb429552Tor Norbye } 7774ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye kind = entry.getEntryKind(); 7784ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 7794ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 7804ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (kind == IClasspathEntry.CPE_SOURCE) { 7814ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye sources.add(workspacePathToFile(entry.getPath())); 7824ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } else if (kind == IClasspathEntry.CPE_LIBRARY) { 7834ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye libraries.add(entry.getPath().toFile()); 7844ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 7854ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // Note that we ignore IClasspathEntry.CPE_CONTAINER: 7864ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // Normal Android Eclipse projects supply both 7874ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // AdtConstants.CONTAINER_FRAMEWORK 7884ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // and 7894ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // AdtConstants.CONTAINER_LIBRARIES 7904ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // here. We ignore the framework classes for obvious reasons, 7914ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // but we also ignore the library container because lint will 7924ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // process the libraries differently. When Eclipse builds a 7934ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // project, it gets the .jar output of the library projects 7944ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // from this container, which means it doesn't have to process 7954ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // the library sources. Lint on the other hand wants to process 7964ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // the source code, so instead it actually looks at the 7974ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // project.properties file to find the libraries, and then it 7984ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // iterates over all the library projects in turn and analyzes 7994ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // those separately (but passing the main project for context, 8004ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // such that the including project's manifest declarations 8014ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // are used for data like minSdkVersion level). 8024ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // 8034ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // Note that this container will also contain *other* 8044ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // libraries (Java libraries, not library projects) that we 8054ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // *should* include. However, we can't distinguish these 8064ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // class path entries from the library project jars, 8074ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // so instead of looking at these, we simply listFiles() in 8084ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // the libs/ folder after processing the classpath info 8094ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8104ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 8114ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye // Add in libraries 8124ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye File libs = new File(project.getDir(), FD_NATIVE_LIBS); 8134ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (libs.isDirectory()) { 8144ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye File[] jars = libs.listFiles(); 8154ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (jars != null) { 8164ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye for (File jar : jars) { 8171fb460987f7d832adf12290f41448d0c16a95972Siva Velusamy if (SdkUtils.endsWith(jar.getPath(), DOT_JAR)) { 8184ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye libraries.add(jar); 8194ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8204ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8214ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8224ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8234ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } catch (CoreException e) { 8244ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye AdtPlugin.log(e, null); 8254ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8264ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8274ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 8284ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (sources == null) { 8294ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye sources = super.getClassPath(project).getSourceFolders(); 8304ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8314ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (classes == null) { 8324ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye classes = super.getClassPath(project).getClassFolders(); 8334ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8344ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye if (libraries == null) { 8354ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye libraries = super.getClassPath(project).getLibraries(); 8364ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8374ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 8384ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye info = new ClassPathInfo(sources, classes, libraries); 8394ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye mProjectInfo.put(project, info); 8404ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8414ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 8424ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye return info; 8434ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye } 8444ae3297a857c6a0c84511b4c5e727360f6958c89Tor Norbye 845a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye /** 846229581314076be1b6f82fe1efed2bd00da340899Tor Norbye * Returns the registry of issues to check from within Eclipse. 847a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye * 848229581314076be1b6f82fe1efed2bd00da340899Tor Norbye * @return the issue registry to use to access detectors and issues 849a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye */ 850229581314076be1b6f82fe1efed2bd00da340899Tor Norbye public static IssueRegistry getRegistry() { 851229581314076be1b6f82fe1efed2bd00da340899Tor Norbye return new BuiltinIssueRegistry(); 8528853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 8538853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 854229581314076be1b6f82fe1efed2bd00da340899Tor Norbye @Override 8557e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Class<? extends Detector> replaceDetector( 8567e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @NonNull Class<? extends Detector> detectorClass) { 857229581314076be1b6f82fe1efed2bd00da340899Tor Norbye return detectorClass; 858a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 859a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye 860ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 8617e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void dispose(@NonNull XmlContext context, @NonNull Document document) { 862c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye IStructuredModel model = (IStructuredModel) context.getProperty(MODEL_PROPERTY); 863c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye assert model != null : context.file; 864c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye if (model != null) { 865c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye model.releaseFromRead(); 866c8e42c3bfdef4941696155e5b333dd6d4075bbf0Tor Norbye } 867a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye } 8688853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 869b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbye @Override 870b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbye @NonNull 871b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbye public IAndroidTarget[] getTargets() { 872b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbye return Sdk.getCurrent().getTargets(); 873b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbye } 874b52aeca0f2e150d7e7e8ceffa897a7ae1f938724Tor Norbye 8753ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye private static class LazyLocation extends Location implements Location.Handle { 8763ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye private final IStructuredDocument mDocument; 8778853b3b92496c5734bbcb75499030bb51a060097Tor Norbye private final IndexedRegion mRegion; 8788853b3b92496c5734bbcb75499030bb51a060097Tor Norbye private Position mStart; 8798853b3b92496c5734bbcb75499030bb51a060097Tor Norbye private Position mEnd; 8808853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 8813ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye public LazyLocation(File file, IStructuredDocument document, IndexedRegion region) { 8828853b3b92496c5734bbcb75499030bb51a060097Tor Norbye super(file, null /*start*/, null /*end*/); 8833ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye mDocument = document; 8848853b3b92496c5734bbcb75499030bb51a060097Tor Norbye mRegion = region; 8858853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 8868853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 8878853b3b92496c5734bbcb75499030bb51a060097Tor Norbye @Override 8888853b3b92496c5734bbcb75499030bb51a060097Tor Norbye public Position getStart() { 8898853b3b92496c5734bbcb75499030bb51a060097Tor Norbye if (mStart == null) { 8903ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye int line = -1; 8913ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye int column = -1; 8923ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye int offset = mRegion.getStartOffset(); 8933ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye 89402e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye if (mRegion instanceof org.w3c.dom.Text && mDocument != null) { 89502e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye // For text nodes, skip whitespace prefix, if any 89602e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye for (int i = offset; 89702e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye i < mRegion.getEndOffset() && i < mDocument.getLength(); i++) { 89802e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye try { 89902e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye char c = mDocument.getChar(i); 90002e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye if (!Character.isWhitespace(c)) { 90102e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye offset = i; 90202e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye break; 90302e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye } 90402e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye } catch (BadLocationException e) { 90502e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye break; 90602e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye } 90702e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye } 90802e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye } 90902e16b51b3986082e14e6121dde71db1898f6d60Tor Norbye 9103ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye if (mDocument != null && offset < mDocument.getLength()) { 9113ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye line = mDocument.getLineOfOffset(offset); 9123ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye column = -1; 9133ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye try { 9143ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye int lineOffset = mDocument.getLineOffset(line); 9153ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye column = offset - lineOffset; 9163ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye } catch (BadLocationException e) { 9173ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye AdtPlugin.log(e, null); 9183ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye } 9193ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye } 9203ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye 9213ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye mStart = new DefaultPosition(line, column, offset); 9228853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 9238853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 9248853b3b92496c5734bbcb75499030bb51a060097Tor Norbye return mStart; 9258853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 9268853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 9278853b3b92496c5734bbcb75499030bb51a060097Tor Norbye @Override 9288853b3b92496c5734bbcb75499030bb51a060097Tor Norbye public Position getEnd() { 9298853b3b92496c5734bbcb75499030bb51a060097Tor Norbye if (mEnd == null) { 9303ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye mEnd = new DefaultPosition(-1, -1, mRegion.getEndOffset()); 9318853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 9328853b3b92496c5734bbcb75499030bb51a060097Tor Norbye 9338853b3b92496c5734bbcb75499030bb51a060097Tor Norbye return mEnd; 9348853b3b92496c5734bbcb75499030bb51a060097Tor Norbye } 93527ed098e750ee9463dfa7a36cef68d219de9eb50Tor Norbye 936ab36f4e7488358dea4ab6b54ee2b7bef3da0232bTor Norbye @Override 9377e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Location resolve() { 9383ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye return this; 9393ce45b249f898697ae82e8c6dd045966227f3438Tor Norbye } 94027ed098e750ee9463dfa7a36cef68d219de9eb50Tor Norbye } 94114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 94214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye private static class EclipseJavaParser implements IJavaParser { 94314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye private static final boolean USE_ECLIPSE_PARSER = true; 94414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye private final Parser mParser; 94514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 94614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye EclipseJavaParser() { 94714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye if (USE_ECLIPSE_PARSER) { 94814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye CompilerOptions options = new CompilerOptions(); 94914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // Read settings from project? Note that this doesn't really matter because 95014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // we will only be parsing, not actually compiling. 95114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye options.complianceLevel = ClassFileConstants.JDK1_6; 95214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye options.sourceLevel = ClassFileConstants.JDK1_6; 95314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye options.targetJDK = ClassFileConstants.JDK1_6; 95414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye options.parseLiteralExpressionsAsConstants = true; 95514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye ProblemReporter problemReporter = new ProblemReporter( 95614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye DefaultErrorHandlingPolicies.exitOnFirstError(), 95714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye options, 95814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye new DefaultProblemFactory()); 95914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye mParser = new Parser(problemReporter, options.parseLiteralExpressionsAsConstants); 96014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye mParser.javadocParser.checkDocComment = false; 96114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } else { 96214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye mParser = null; 96314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 96414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 96514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 96614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye @Override 9677e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public lombok.ast.Node parseJava(@NonNull JavaContext context) { 96814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye if (USE_ECLIPSE_PARSER) { 96914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // Use Eclipse's compiler 97014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye EcjTreeConverter converter = new EcjTreeConverter(); 97114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye String code = context.getContents(); 97214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 97314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye CompilationUnit sourceUnit = new CompilationUnit(code.toCharArray(), 97414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye context.file.getName(), "UTF-8"); //$NON-NLS-1$ 97514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0); 97614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye CompilationUnitDeclaration unit = null; 97714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye try { 97814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye unit = mParser.parse(sourceUnit, compilationResult); 97914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } catch (AbortCompilation e) { 980afb7b2c7b91831381e5f1f096738654dcd1bb82dTor Norbye // No need to report Java parsing errors while running in Eclipse. 981afb7b2c7b91831381e5f1f096738654dcd1bb82dTor Norbye // Eclipse itself will already provide problem markers for these files, 982afb7b2c7b91831381e5f1f096738654dcd1bb82dTor Norbye // so all this achieves is creating "multiple annotations on this line" 983afb7b2c7b91831381e5f1f096738654dcd1bb82dTor Norbye // tooltips instead. 98414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return null; 98514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 98614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye if (unit == null) { 98714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return null; 98814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 98914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 99014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye try { 99114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye converter.visit(code, unit); 99214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye List<? extends lombok.ast.Node> nodes = converter.getAll(); 99314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 99414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // There could be more than one node when there are errors; pick out the 99514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // compilation unit node 99614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye for (lombok.ast.Node node : nodes) { 99737d5a9bbdc2895921cd0f636777efe2d3bad4e5bTor Norbye if (node instanceof lombok.ast.CompilationUnit) { 99814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return node; 99914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 100014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 100114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 100214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return null; 100314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } catch (Throwable t) { 100414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye AdtPlugin.log(t, "Failed converting ECJ parse tree to Lombok for file %1$s", 100514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye context.file.getPath()); 100614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return null; 100714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 100814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } else { 100914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // Use Lombok for now 101014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye Source source = new Source(context.getContents(), context.file.getName()); 101114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye List<lombok.ast.Node> nodes = source.getNodes(); 101214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 101314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // Don't analyze files containing errors 101414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye List<ParseProblem> problems = source.getProblems(); 101514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye if (problems != null && problems.size() > 0) { 1016a2a7d644db6b742fda413600f62c64c1133a6c21Tor Norbye /* Silently ignore the errors. There are still some bugs in Lombok/Parboiled 1017a2a7d644db6b742fda413600f62c64c1133a6c21Tor Norbye * (triggered if you run lint on the AOSP framework directory for example), 1018a2a7d644db6b742fda413600f62c64c1133a6c21Tor Norbye * and having these show up as fatal errors when it's really a tool bug 1019a2a7d644db6b742fda413600f62c64c1133a6c21Tor Norbye * is bad. To make matters worse, the error messages aren't clear: 1020a2a7d644db6b742fda413600f62c64c1133a6c21Tor Norbye * http://code.google.com/p/projectlombok/issues/detail?id=313 102114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye for (ParseProblem problem : problems) { 102214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye lombok.ast.Position position = problem.getPosition(); 102314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye Location location = Location.create(context.file, 102414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye context.getContents(), position.getStart(), position.getEnd()); 102514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye String message = problem.getMessage(); 102614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye context.report( 102714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye IssueRegistry.PARSER_ERROR, location, 102814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye message, 102914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye null); 103014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 103114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 1032a2a7d644db6b742fda413600f62c64c1133a6c21Tor Norbye */ 103314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return null; 103414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 103514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 103614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // There could be more than one node when there are errors; pick out the 103714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye // compilation unit node 103814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye for (lombok.ast.Node node : nodes) { 103914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye if (node instanceof lombok.ast.CompilationUnit) { 104014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return node; 104114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 104214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 104314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return null; 104414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 104514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 104614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 104714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye @Override 10487e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Location getLocation(@NonNull JavaContext context, 10497e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @NonNull lombok.ast.Node node) { 105014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye lombok.ast.Position position = node.getPosition(); 105114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return Location.create(context.file, context.getContents(), 105214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye position.getStart(), position.getEnd()); 105314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 105414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 105514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye @Override 10567e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Handle createLocationHandle(@NonNull JavaContext context, 10577e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @NonNull lombok.ast.Node node) { 105814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return new LocationHandle(context.file, node); 105914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 106014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 106114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye @Override 10627e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public void dispose(@NonNull JavaContext context, 10637e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye @NonNull lombok.ast.Node compilationUnit) { 106414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 106514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 106614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye /* Handle for creating positions cheaply and returning full fledged locations later */ 106714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye private class LocationHandle implements Handle { 106814312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye private File mFile; 106914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye private lombok.ast.Node mNode; 10703e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye private Object mClientData; 107114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 107214312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye public LocationHandle(File file, lombok.ast.Node node) { 107314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye mFile = file; 107414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye mNode = node; 107514312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 107614312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye 107714312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye @Override 10787e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye public @NonNull Location resolve() { 107914312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye lombok.ast.Position pos = mNode.getPosition(); 108014312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye return Location.create(mFile, null /*contents*/, pos.getStart(), pos.getEnd()); 108114312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 10823e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye 10833e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye @Override 10843e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye public void setClientData(@Nullable Object clientData) { 10853e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye mClientData = clientData; 10863e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye } 10873e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye 10883e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye @Override 10893e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye @Nullable 10903e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye public Object getClientData() { 10913e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye return mClientData; 10923e10306ab1812b2c141e75fb36e2f5c92eeefd28Tor Norbye } 109314312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 109414312a9603fab9e711639cfc19d5ea1de17250b1Tor Norbye } 1095a85107f7d763276a5a040cf68e2046ac54202015Tor Norbye} 1096229581314076be1b6f82fe1efed2bd00da340899Tor Norbye 1097