• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.ide.eclipse.adt.internal.resources.manager;
17 
18 import static com.android.ide.eclipse.adt.AdtConstants.MARKER_AAPT_COMPILE;
19 import static org.eclipse.core.resources.IResource.DEPTH_ONE;
20 import static org.eclipse.core.resources.IResource.DEPTH_ZERO;
21 
22 import com.android.ide.common.resources.ResourceRepository;
23 import com.android.ide.common.resources.ScanningContext;
24 import com.android.ide.eclipse.adt.AdtPlugin;
25 import com.android.ide.eclipse.adt.internal.build.AaptParser;
26 import com.android.util.Pair;
27 
28 import org.eclipse.core.resources.IFolder;
29 import org.eclipse.core.resources.IProject;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.runtime.CoreException;
32 
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Set;
38 
39 /**
40  * An {@link IdeScanningContext} is a specialized {@link ScanningContext} which
41  * carries extra information about the scanning state, such as which file is
42  * currently being scanned, and which files have been scanned in the past, such
43  * that at the end of a scan we can mark and clear errors, etc.
44  */
45 public class IdeScanningContext extends ScanningContext {
46     private final IProject mProject;
47     private final List<IResource> mScannedResources = new ArrayList<IResource>();
48     private IResource mCurrentFile;
49     private List<Pair<IResource, String>> mErrors;
50     private Set<IProject> mFullAaptProjects;
51 
52     /**
53      * Constructs a new {@link IdeScanningContext}
54      *
55      * @param repository the associated {@link ResourceRepository}
56      * @param project the associated project
57      */
IdeScanningContext(ResourceRepository repository, IProject project)58     public IdeScanningContext(ResourceRepository repository, IProject project) {
59         super(repository);
60         mProject = project;
61     }
62 
63     @Override
addError(String error)64     public void addError(String error) {
65         super.addError(error);
66 
67         if (mErrors == null) {
68             mErrors = new ArrayList<Pair<IResource,String>>();
69         }
70         mErrors.add(Pair.of(mCurrentFile, error));
71     }
72 
73     /**
74      * Notifies the context that the given resource is about to be scanned.
75      *
76      * @param resource the resource about to be scanned
77      */
startScanning(IResource resource)78     public void startScanning(IResource resource) {
79         assert mCurrentFile == null : mCurrentFile;
80         mCurrentFile = resource;
81         mScannedResources.add(resource);
82     }
83 
84     /**
85      * Notifies the context that the given resource has been scanned.
86      *
87      * @param resource the resource that was scanned
88      */
finishScanning(IResource resource)89     public void finishScanning(IResource resource) {
90         assert mCurrentFile != null;
91         mCurrentFile = null;
92     }
93 
94     /**
95      * Process any errors found to add error markers in the affected files (and
96      * also clear up any aapt errors in files that are no longer applicable)
97      *
98      * @param async if true, delay updating markers until the next display
99      *            thread event loop update
100      */
updateMarkers(boolean async)101     public void updateMarkers(boolean async) {
102         // Run asynchronously? This is necessary for example when adding markers
103         // as the result of a resource change notification, since at that point the
104         // resource tree is locked for modifications and attempting to create a
105         // marker will throw a org.eclipse.core.internal.resources.ResourceException.
106         if (async) {
107             AdtPlugin.getDisplay().asyncExec(new Runnable() {
108                 public void run() {
109                     updateMarkers(false);
110                 }
111             });
112             return;
113         }
114 
115         // First clear out old/previous markers
116         for (IResource resource :mScannedResources) {
117             try {
118                 if (resource.exists()) {
119                     int depth = resource instanceof IFolder ? DEPTH_ONE : DEPTH_ZERO;
120                     resource.deleteMarkers(MARKER_AAPT_COMPILE, true, depth);
121                 }
122             } catch (CoreException ce) {
123                 // Pass
124             }
125         }
126 
127         // Add new errors
128         if (mErrors != null && mErrors.size() > 0) {
129             List<String> errors = new ArrayList<String>();
130             for (Pair<IResource, String> pair : mErrors) {
131                 errors.add(pair.getSecond());
132             }
133             AaptParser.parseOutput(errors, mProject);
134         }
135     }
136 
137     @Override
needsFullAapt()138     public boolean needsFullAapt() {
139         return super.needsFullAapt();
140     }
141 
142     @Override
requestFullAapt()143     protected void requestFullAapt() {
144         super.requestFullAapt();
145 
146         if (mCurrentFile != null) {
147             if (mFullAaptProjects == null) {
148                 mFullAaptProjects = new HashSet<IProject>();
149             }
150             mFullAaptProjects.add(mCurrentFile.getProject());
151         } else {
152             assert false : "No current context to apply IdeScanningContext to";
153         }
154     }
155 
156     /**
157      * Returns the collection of projects that scanned resources have requested
158      * a full aapt for.
159      *
160      * @return a collection of projects that scanned resources requested full
161      *         aapt runs for, or null
162      */
getAaptRequestedProjects()163     public Collection<IProject> getAaptRequestedProjects() {
164         return mFullAaptProjects;
165     }
166 }
167