Skip to content

Commit 34c5331

Browse files
MCMicStbroyer
authored andcommitted
FIX: LookupMethodCreator create too large method
Bug: #8611 Bug-Link: #8611 Change-Id: I6156581364a571621234b9c1d7fd597beaa27c7c
1 parent 26c080e commit 34c5331

File tree

9 files changed

+922
-38
lines changed

9 files changed

+922
-38
lines changed

user/src/com/google/gwt/i18n/rebind/ConstantsWithLookupImplCreator.java

Lines changed: 149 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,31 +25,69 @@
2525
import com.google.gwt.core.ext.typeinfo.TypeOracleException;
2626
import com.google.gwt.i18n.rebind.AbstractResource.ResourceList;
2727
import com.google.gwt.i18n.shared.GwtLocale;
28-
import com.google.gwt.user.rebind.AbstractMethodCreator;
28+
import com.google.gwt.thirdparty.guava.common.collect.Lists;
2929
import com.google.gwt.user.rebind.SourceWriter;
3030

31+
import java.text.MessageFormat;
32+
import java.util.ArrayList;
33+
import java.util.Collections;
3134
import java.util.HashMap;
35+
import java.util.Iterator;
36+
import java.util.List;
3237
import java.util.Map;
38+
import java.util.Map.Entry;
3339

3440
class ConstantsWithLookupImplCreator extends ConstantsImplCreator {
41+
42+
/**
43+
* Used partition size if no one is specified.
44+
*
45+
* Used in constructor without a partition size.
46+
*/
47+
private static final int DEFAULT_PARTITIONS_SIZE = 500;
48+
3549
final JMethod[] allInterfaceMethods;
3650

37-
private final Map<String, AbstractMethodCreator> namesToMethodCreators = new HashMap<String, AbstractMethodCreator>();
51+
private final Map<String, LookupMethodCreator> namesToMethodCreators = new HashMap<>();
52+
53+
private final Map<JMethod, List<List<JMethod>>> neededPartitionLookups = new HashMap<>();
54+
55+
private final int partitionsSize;
3856

3957
/**
40-
* Constructor for <code>ConstantsWithLookupImplCreator</code>.
58+
* Constructor for <code>ConstantsWithLookupImplCreator</code>. The default partition size of
59+
* {@value #DEFAULT_PARTITIONS_SIZE} is used.
4160
*
4261
* @param logger logger to print errors
4362
* @param writer <code>Writer</code> to print to
4463
* @param localizableClass class/interface to conform to
4564
* @param resourceList resource bundle used to generate the class
4665
* @param oracle types
4766
* @throws UnableToCompleteException
67+
*
68+
* @see LookupMethodCreator#DEFAULT_PARTITIONS_SIZE
4869
*/
4970
ConstantsWithLookupImplCreator(TreeLogger logger, SourceWriter writer,
5071
JClassType localizableClass, ResourceList resourceList, TypeOracle oracle)
5172
throws UnableToCompleteException {
73+
this(logger, writer, localizableClass, resourceList, oracle, DEFAULT_PARTITIONS_SIZE);
74+
}
75+
76+
/**
77+
* Constructor for <code>ConstantsWithLookupImplCreator</code>.
78+
*
79+
* @param logger logger to print errors
80+
* @param writer <code>Writer</code> to print to
81+
* @param localizableClass class/interface to conform to
82+
* @param resourceList resource bundle used to generate the class
83+
* @param oracle types
84+
* @throws UnableToCompleteException
85+
*/
86+
ConstantsWithLookupImplCreator(TreeLogger logger, SourceWriter writer,
87+
JClassType localizableClass, ResourceList resourceList, TypeOracle oracle,
88+
int partitionsSize) throws UnableToCompleteException {
5289
super(logger, writer, localizableClass, resourceList, oracle);
90+
this.partitionsSize = partitionsSize;
5391
try {
5492

5593
// Boolean
@@ -63,7 +101,9 @@ public void printReturnTarget() {
63101

64102
@Override
65103
public String returnTemplate() {
66-
return "boolean answer = {0}();\ncache.put(\"{0}\",new Boolean(answer));\nreturn answer;";
104+
return "boolean answer = {0}();\n"
105+
+ "cache.put(\"{0}\",new Boolean(answer));\n"
106+
+ "return answer;";
67107
}
68108
};
69109
namesToMethodCreators.put("getBoolean", booleanMethod);
@@ -79,7 +119,9 @@ public void printReturnTarget() {
79119

80120
@Override
81121
public String returnTemplate() {
82-
return "double answer = {0}();\ncache.put(\"{0}\",new Double(answer));\nreturn answer;";
122+
return "double answer = {0}();\n"
123+
+ "cache.put(\"{0}\",new Double(answer));\n"
124+
+ "return answer;";
83125
}
84126
};
85127
namesToMethodCreators.put("getDouble", doubleMethod);
@@ -94,7 +136,9 @@ public void printReturnTarget() {
94136

95137
@Override
96138
public String returnTemplate() {
97-
return "int answer = {0}();\ncache.put(\"{0}\",new Integer(answer));\nreturn answer;";
139+
return "int answer = {0}();\n"
140+
+ "cache.put(\"{0}\",new Integer(answer));\n"
141+
+ "return answer;";
98142
}
99143
};
100144

@@ -105,7 +149,9 @@ public String returnTemplate() {
105149
LookupMethodCreator floatMethod = new LookupMethodCreator(this, floatType) {
106150
@Override
107151
public String returnTemplate() {
108-
String val = "float answer = {0}();\ncache.put(\"{0}\", new Float(answer));\nreturn answer;";
152+
String val = "float answer = {0}();\n"
153+
+ "cache.put(\"{0}\", new Float(answer));\n"
154+
+ "return answer;";
109155
return val;
110156
}
111157

@@ -132,7 +178,9 @@ public String getReturnTypeName() {
132178
stringType) {
133179
@Override
134180
public String returnTemplate() {
135-
return "String answer = {0}();\ncache.put(\"{0}\",answer);\nreturn answer;";
181+
return "String answer = {0}();\n"
182+
+ "cache.put(\"{0}\",answer);\n"
183+
+ "return answer;";
136184
}
137185
};
138186
namesToMethodCreators.put("getString", stringMethod);
@@ -149,6 +197,12 @@ public String returnTemplate() {
149197
}
150198
}
151199

200+
@Override
201+
protected void classEpilog() {
202+
createNeededPartitionLookups();
203+
super.classEpilog();
204+
}
205+
152206
/**
153207
* Create the method body associated with the given method. Arguments are
154208
* arg0...argN.
@@ -159,16 +213,78 @@ protected void emitMethodBody(TreeLogger logger, JMethod method,
159213
checkMethod(logger, method);
160214
if (method.getParameters().length == 1) {
161215
String name = method.getName();
162-
AbstractMethodCreator c = namesToMethodCreators.get(name);
216+
LookupMethodCreator c = getLookupMethodCreator(name);
163217
if (c != null) {
164-
c.createMethodFor(logger, method, name, null, locale);
218+
createMethodWithPartitionCheckFor(c, method);
165219
return;
166220
}
167221
}
168222
// fall through
169223
super.emitMethodBody(logger, method, locale);
170224
}
171225

226+
void addNeededPartitionLookups(JMethod targetMethod,
227+
List<List<JMethod>> methodToCreatePartitionLookups) {
228+
neededPartitionLookups.put(targetMethod, methodToCreatePartitionLookups);
229+
}
230+
231+
void createMethodWithPartitionCheckFor(LookupMethodCreator methodCreator, JMethod targetMethod) {
232+
List<List<JMethod>> methodPartitions = findMethodsToCreateWithPartitionSize(targetMethod,
233+
methodCreator.getReturnType());
234+
235+
String nextPartitionMethod = null;
236+
final List<List<JMethod>> methodToCreatePartitionLookups;
237+
final List<JMethod> methodsToCreate;
238+
if (methodPartitions.size() > 1) {
239+
nextPartitionMethod = createPartitionMethodName(targetMethod, 0);
240+
methodsToCreate = methodPartitions.get(0);
241+
methodToCreatePartitionLookups = methodPartitions.subList(1, methodPartitions.size());
242+
} else {
243+
methodsToCreate = methodPartitions.isEmpty() ? Collections.<JMethod> emptyList()
244+
: methodPartitions.get(0);
245+
methodToCreatePartitionLookups = Collections.emptyList();
246+
}
247+
addNeededPartitionLookups(targetMethod, methodToCreatePartitionLookups);
248+
methodCreator.createCacheLookupFor();
249+
methodCreator.createMethodFor(targetMethod, methodsToCreate, nextPartitionMethod);
250+
}
251+
252+
String createPartitionMethodName(JMethod targetMethod, int partitionIndex) {
253+
final String templatePartitionMethodName = "{0}FromPartition{1}";
254+
return MessageFormat.format(templatePartitionMethodName, new Object[] {
255+
targetMethod.getName(), partitionIndex});
256+
}
257+
258+
List<JMethod> findAllMethodsToCreate(JMethod targetMethod, JType methodReturnType) {
259+
JMethod[] allMethods = allInterfaceMethods;
260+
JType erasedType = methodReturnType.getErasedType();
261+
List<JMethod> methodsToCreate = new ArrayList<>();
262+
for (JMethod methodToCheck : allMethods) {
263+
if (methodToCheck.getReturnType().getErasedType().equals(erasedType)
264+
&& methodToCheck != targetMethod) {
265+
methodsToCreate.add(methodToCheck);
266+
}
267+
}
268+
return methodsToCreate;
269+
}
270+
271+
List<List<JMethod>> findMethodsToCreateWithPartitionSize(JMethod targetMethod,
272+
JType methodReturnType) {
273+
List<JMethod> allMethodsToCreate = findAllMethodsToCreate(targetMethod, methodReturnType);
274+
return Lists.partition(allMethodsToCreate, partitionsSize);
275+
}
276+
277+
LookupMethodCreator getLookupMethodCreator(String name) {
278+
return namesToMethodCreators.get(name);
279+
}
280+
281+
/**
282+
* Visible for testing only.
283+
*/
284+
Map<JMethod, List<List<JMethod>>> getNeededPartitionLookups() {
285+
return neededPartitionLookups;
286+
}
287+
172288
/**
173289
* Checks that the method has the right structure to implement
174290
* <code>Constant</code>.
@@ -177,7 +293,7 @@ protected void emitMethodBody(TreeLogger logger, JMethod method,
177293
*/
178294
private void checkMethod(TreeLogger logger, JMethod method)
179295
throws UnableToCompleteException {
180-
if (namesToMethodCreators.get(method.getName()) != null) {
296+
if (getLookupMethodCreator(method.getName()) != null) {
181297
JParameter[] params = method.getParameters();
182298
// user may have specified a method named getInt/etc with no parameters
183299
// this isn't a conflict, so treat them like any other Constant methods
@@ -195,4 +311,26 @@ private void checkMethod(TreeLogger logger, JMethod method)
195311
checkConstantMethod(logger, method);
196312
}
197313
}
314+
315+
private void createNeededPartitionLookups() {
316+
for (Entry<JMethod, List<List<JMethod>>> neededPartitionLookup :
317+
neededPartitionLookups.entrySet()) {
318+
JMethod targetMethod = neededPartitionLookup.getKey();
319+
LookupMethodCreator lookupMethodCreator = getLookupMethodCreator(targetMethod.getName());
320+
List<List<JMethod>> methodForPartitionLookups = neededPartitionLookup.getValue();
321+
int partitionStartIndex = 0;
322+
Iterator<List<JMethod>> neededPartitionIterator = methodForPartitionLookups.iterator();
323+
while (neededPartitionIterator.hasNext()) {
324+
String currentPartitionLookupMethodName = createPartitionMethodName(targetMethod,
325+
partitionStartIndex++);
326+
List<JMethod> methodsToCreate = neededPartitionIterator.next();
327+
String nextPartitionMethod = null;
328+
if (neededPartitionIterator.hasNext()) {
329+
nextPartitionMethod = createPartitionMethodName(targetMethod, partitionStartIndex);
330+
}
331+
lookupMethodCreator.createPartitionLookup(currentPartitionLookupMethodName, targetMethod,
332+
methodsToCreate, nextPartitionMethod);
333+
}
334+
}
335+
}
198336
}

0 commit comments

Comments
 (0)