]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2007, 2011 IBM Corporation and others. | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.internal.corext.dom; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.Arrays; | |
15 | import java.util.Collection; | |
16 | import java.util.Hashtable; | |
17 | import java.util.Iterator; | |
18 | import java.util.List; | |
19 | ||
20 | import org.eclipse.core.runtime.IProgressMonitor; | |
21 | import org.eclipse.core.runtime.NullProgressMonitor; | |
22 | import org.eclipse.core.runtime.SubProgressMonitor; | |
23 | ||
24 | import org.eclipse.jdt.core.ICompilationUnit; | |
25 | import org.eclipse.jdt.core.IJavaProject; | |
26 | import org.eclipse.jdt.core.dom.ASTParser; | |
27 | import org.eclipse.jdt.core.dom.ASTRequestor; | |
28 | import org.eclipse.jdt.core.dom.IBinding; | |
29 | ||
30 | import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; | |
31 | ||
32 | /** | |
33 | * Creates AST from a set of compilation units. Uses the | |
34 | * batch parser. Splits the set of compilation units in subsets | |
35 | * such that it is unlikely that a out of memory exception will occur. | |
36 | * | |
37 | * @since 3.4 | |
38 | */ | |
39 | public class ASTBatchParser { | |
40 | ||
41 | private static final int MAX_AT_ONCE; | |
42 | static { | |
43 | long maxMemory= Runtime.getRuntime().maxMemory(); | |
44 | int ratio= (int) Math.round((double) maxMemory / (64 * 0x100000)); | |
45 | switch (ratio) { | |
46 | case 0: | |
47 | MAX_AT_ONCE= 25; | |
48 | break; | |
49 | case 1: | |
50 | MAX_AT_ONCE= 100; | |
51 | break; | |
52 | case 2: | |
53 | MAX_AT_ONCE= 200; | |
54 | break; | |
55 | case 3: | |
56 | MAX_AT_ONCE= 300; | |
57 | break; | |
58 | case 4: | |
59 | MAX_AT_ONCE= 400; | |
60 | break; | |
61 | default: | |
62 | MAX_AT_ONCE= 500; | |
63 | break; | |
64 | } | |
65 | } | |
66 | ||
67 | /** | |
68 | * Creates ASTs for each compilation unit in <code>units</code>. | |
69 | * <p> | |
70 | * <code>ASTRequestor.acceptAST</code> is called in no particular order to | |
71 | * pass the compilation unit and the corresponding AST to <code>requestor</code>. | |
72 | * </p> | |
73 | * <p> | |
74 | * The <code>bindingKeys</code> parameter specifies bindings keys | |
75 | * ({@link IBinding#getKey()}) that are to be looked up. | |
76 | * </p> | |
77 | * | |
78 | * @param compilationUnits the compilation units to create ASTs for | |
79 | * @param bindingKeys the binding keys to create bindings for | |
80 | * @param requestor the AST requestor that collects abstract syntax trees and bindings | |
81 | * @param monitor the progress monitor used to report progress and request cancelation, | |
82 | * or <code>null</code> if none | |
83 | * @see ASTParser#createASTs(ICompilationUnit[], String[], ASTRequestor, IProgressMonitor) | |
84 | */ | |
85 | public final void createASTs(ICompilationUnit[] compilationUnits, String[] bindingKeys, ASTRequestor requestor, IProgressMonitor monitor) { | |
86 | if (compilationUnits.length == 0) | |
87 | return; | |
88 | ||
89 | if (monitor == null) | |
90 | monitor= new NullProgressMonitor(); | |
91 | ||
92 | monitor.beginTask("", compilationUnits.length); //$NON-NLS-1$ | |
93 | try { | |
94 | ||
95 | ICompilationUnit[][] splited= splitByProject(compilationUnits); | |
96 | for (int i= 0; i < splited.length; i++) { | |
97 | ICompilationUnit[] units= splited[i]; | |
98 | ||
99 | if (units.length <= MAX_AT_ONCE) { | |
100 | createParser(units[0].getJavaProject()).createASTs(units, bindingKeys, requestor, new SubProgressMonitor(monitor, units.length)); | |
101 | } else { | |
102 | List<ICompilationUnit> list= Arrays.asList(units); | |
103 | int end= 0; | |
104 | int cursor= 0; | |
105 | while (cursor < units.length) { | |
106 | end= Math.min(end + MAX_AT_ONCE, units.length); | |
107 | List<ICompilationUnit> toParse= list.subList(cursor, end); | |
108 | ||
109 | createParser(units[0].getJavaProject()).createASTs(toParse.toArray(new ICompilationUnit[toParse.size()]), bindingKeys, requestor, | |
110 | new SubProgressMonitor(monitor, toParse.size())); | |
111 | cursor= end; | |
112 | } | |
113 | } | |
114 | } | |
115 | } finally { | |
116 | monitor.done(); | |
117 | } | |
118 | } | |
119 | ||
120 | /** | |
121 | * Creates a new parser which can be used to create ASTs | |
122 | * for compilation units in <code>project</code> | |
123 | * <p> | |
124 | * Subclasses may override | |
125 | * </p> | |
126 | * | |
127 | * @param project the project for which ASTs are been generated | |
128 | * @return an AST parser capable of creating ASTs of compilation units in project | |
129 | */ | |
130 | protected ASTParser createParser(IJavaProject project) { | |
131 | ASTParser result= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); | |
132 | result.setResolveBindings(true); | |
133 | result.setProject(project); | |
134 | ||
135 | return result; | |
136 | } | |
137 | ||
138 | private static ICompilationUnit[][] splitByProject(ICompilationUnit[] units) { | |
139 | if (hasOnlyOneProject(units)) | |
140 | return new ICompilationUnit[][] { units }; | |
141 | ||
142 | Hashtable<IJavaProject, ArrayList<ICompilationUnit>> projectTable= new Hashtable<IJavaProject, ArrayList<ICompilationUnit>>(); | |
143 | ||
144 | for (int i= 0; i < units.length; i++) { | |
145 | ICompilationUnit unit= units[i]; | |
146 | ArrayList<ICompilationUnit> list= projectTable.get(unit.getJavaProject()); | |
147 | if (list == null) { | |
148 | list= new ArrayList<ICompilationUnit>(); | |
149 | projectTable.put(unit.getJavaProject(), list); | |
150 | } | |
151 | list.add(unit); | |
152 | } | |
153 | ||
154 | Collection<ArrayList<ICompilationUnit>> values= projectTable.values(); | |
155 | ||
156 | ICompilationUnit[][] result= new ICompilationUnit[values.size()][]; | |
157 | int i= 0; | |
158 | for (Iterator<ArrayList<ICompilationUnit>> iterator= values.iterator(); iterator.hasNext();) { | |
159 | ArrayList<ICompilationUnit> cus= iterator.next(); | |
160 | result[i]= cus.toArray(new ICompilationUnit[cus.size()]); | |
161 | i++; | |
162 | } | |
163 | ||
164 | return result; | |
165 | } | |
166 | ||
167 | private static boolean hasOnlyOneProject(ICompilationUnit[] units) { | |
168 | IJavaProject javaProject= units[0].getJavaProject(); | |
169 | for (int i= 1; i < units.length; i++) { | |
170 | if (!javaProject.equals(units[i].getJavaProject())) | |
171 | return false; | |
172 | } | |
173 | ||
174 | return true; | |
175 | } | |
176 | } |