]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/TypeVariableUtil.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / structure / TypeVariableUtil.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 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 *******************************************************************************/
11package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13import java.util.ArrayList;
14import java.util.Arrays;
15import java.util.HashSet;
16import java.util.List;
17import java.util.Set;
18
19import org.eclipse.core.runtime.Assert;
20
21import org.eclipse.jdt.core.IField;
22import org.eclipse.jdt.core.IMember;
23import org.eclipse.jdt.core.IMethod;
24import org.eclipse.jdt.core.IType;
25import org.eclipse.jdt.core.ITypeParameter;
26import org.eclipse.jdt.core.JavaModelException;
27import org.eclipse.jdt.core.Signature;
28
29import org.eclipse.jdt.internal.ui.JavaPlugin;
30
31/**
32 * Utilities to create mappings between type variables of different types in a type hierarchy.
33 */
34public final class TypeVariableUtil {
35
36 /**
37 * Returns the composition of two type variable mappings. The type variables signatures can have an arbitrary format.
38 *
39 * @param first
40 * the first type variable mapping
41 * @param second
42 * the second type variable mapping
43 * @return the possibly empty composed type variable mapping
44 */
45 public static TypeVariableMaplet[] composeMappings(final TypeVariableMaplet[] first, final TypeVariableMaplet[] second) {
46 Assert.isNotNull(first);
47 Assert.isNotNull(second);
48
49 if (first.length == 0)
50 return first;
51 else if (second.length == 0)
52 return second;
53 else {
54 TypeVariableMaplet source= null;
55 TypeVariableMaplet target= null;
56 final Set<TypeVariableMaplet> set= new HashSet<TypeVariableMaplet>(first.length * second.length);
57 for (int index= 0; index < first.length; index++) {
58 for (int offset= 0; offset < second.length; offset++) {
59 source= first[index];
60 target= second[offset];
61 if (source.getTargetIndex() == target.getSourceIndex() && source.getTargetName().equals(target.getSourceName()))
62 set.add(new TypeVariableMaplet(source.getSourceName(), index, target.getTargetName(), offset));
63 }
64 }
65 final TypeVariableMaplet[] mapping= new TypeVariableMaplet[set.size()];
66 set.toArray(mapping);
67 return mapping;
68 }
69 }
70
71 /**
72 * Extracts the type variables from a signature
73 *
74 * @param signature
75 * the signature to extract the type variables from
76 * @param variables
77 * the set of variables to fill in
78 */
79 private static void extractTypeVariables(final String signature, final Set<String> variables) {
80 Assert.isNotNull(signature);
81 Assert.isNotNull(variables);
82
83 final String[] arguments= Signature.getTypeArguments(signature);
84 if (arguments.length == 0) {
85 variables.add(Signature.toString(signature));
86 } else {
87 for (int index= 0; index < arguments.length; index++)
88 variables.add(Signature.toString(arguments[index]));
89 }
90 }
91
92 /**
93 * Returns the type variables referenced in the signature of the specified member.
94 *
95 * @param declaring
96 * The declaring type of the specified member
97 * @param member
98 * the member to get its type variables. Can be a type, field or a method.
99 * @return a possibly empty array of type variable candidates
100 * @throws JavaModelException
101 * if the signature of the specified member could not be resolved
102 */
103 private static String[] getReferencedVariables(final IType declaring, final IMember member) throws JavaModelException {
104
105 Assert.isNotNull(declaring);
106 Assert.isNotNull(member);
107
108 final String[] variables= parametersToVariables(declaring.getTypeParameters());
109 String[] result= new String[0];
110 if (member instanceof IField) {
111 final String signature= ((IField) member).getTypeSignature();
112 final String[] signatures= getVariableSignatures(signature);
113 if (signatures.length == 0) {
114 final String variable= Signature.toString(signature);
115 for (int index= 0; index < variables.length; index++) {
116 if (variable.equals(variables[index])) {
117 result= new String[] { variable};
118 break;
119 }
120 }
121 } else {
122 result= new String[signatures.length];
123 for (int index= 0; index < result.length; index++)
124 result[index]= Signature.toString(signatures[index]);
125 }
126 } else if (member instanceof IMethod) {
127 final IMethod method= (IMethod) member;
128 final HashSet<String> set= new HashSet<String>();
129 final String[] types= method.getParameterTypes();
130 for (int index= 0; index < types.length; index++)
131 extractTypeVariables(types[index], set);
132 extractTypeVariables(method.getReturnType(), set);
133 final String[] arguments= parametersToVariables(((IMethod) member).getTypeParameters());
134 for (int index= 0; index < arguments.length; index++)
135 set.add(arguments[index]);
136 result= new String[set.size()];
137 set.toArray(result);
138 } else if (member instanceof IType)
139 result= parametersToVariables(((IType) member).getTypeParameters());
140 else {
141 JavaPlugin.logErrorMessage("Unexpected sub-type of IMember: " + member.getClass().getName()); //$NON-NLS-1$
142 Assert.isTrue(false);
143 }
144
145 final List<String> list= new ArrayList<String>(variables.length);
146 String variable= null;
147 for (int index= 0; index < variables.length; index++) {
148 variable= variables[index];
149 for (int offset= 0; offset < result.length; offset++)
150 if (variable.equals(result[offset]))
151 list.add(result[offset]);
152 }
153 result= new String[list.size()];
154 list.toArray(result);
155 return result;
156 }
157
158 /**
159 * Returns all type variable names of the indicated member not mapped by the specified type variable mapping.
160 *
161 * @param mapping
162 * the type variable mapping. The entries of this mapping must be simple type variable names.
163 * @param declaring
164 * the declaring type of the indicated member
165 * @param member
166 * the member to determine its unmapped type variable names
167 * @return a possibly empty array of unmapped type variable names
168 * @throws JavaModelException
169 * if the type parameters of the member could not be determined
170 */
171 public static String[] getUnmappedVariables(final TypeVariableMaplet[] mapping, final IType declaring, final IMember member) throws JavaModelException {
172
173 Assert.isNotNull(mapping);
174 Assert.isNotNull(declaring);
175 Assert.isNotNull(member);
176
177 List<String> list= null;
178 final String[] types= getReferencedVariables(declaring, member);
179 if (mapping.length == 0) {
180 list= new ArrayList<String>(types.length);
181 list.addAll(Arrays.asList(types));
182 } else {
183 final Set<String> mapped= new HashSet<String>(types.length);
184 String type= null;
185 for (int index= 0; index < types.length; index++) {
186 for (int offset= 0; offset < mapping.length; offset++) {
187 type= types[index];
188 if (mapping[offset].getSourceName().equals(type))
189 mapped.add(type);
190 }
191 }
192 list= new ArrayList<String>(types.length - mapped.size());
193 for (int index= 0; index < types.length; index++) {
194 type= types[index];
195 if (!mapped.contains(type))
196 list.add(type);
197 }
198 }
199 final String[] result= new String[list.size()];
200 list.toArray(result);
201 return result;
202 }
203
204 /**
205 * Returns the type variable signatures of the specified parameterized type signature, or an empty array if none.
206 *
207 * @param signature
208 * the signature to get its type variable signatures from. The signature must be a parameterized type signature.
209 * @return a possibly empty array of type variable signatures
210 * @see Signature#getTypeArguments(String)
211 */
212 private static String[] getVariableSignatures(final String signature) {
213 Assert.isNotNull(signature);
214
215 String[] result= null;
216 try {
217 result= Signature.getTypeArguments(signature);
218 } catch (IllegalArgumentException exception) {
219 result= new String[0];
220 }
221 return result;
222 }
223
224 /**
225 * Returns the reversed type variable mapping of the specified mapping.
226 *
227 * @param mapping
228 * the mapping to inverse
229 * @return the possibly empty inverse mapping
230 */
231 public static TypeVariableMaplet[] inverseMapping(final TypeVariableMaplet[] mapping) {
232 Assert.isNotNull(mapping);
233
234 final TypeVariableMaplet[] result= new TypeVariableMaplet[mapping.length];
235 TypeVariableMaplet maplet= null;
236 for (int index= 0; index < mapping.length; index++) {
237 maplet= mapping[index];
238 result[index]= new TypeVariableMaplet(maplet.getTargetName(), maplet.getTargetIndex(), maplet.getSourceName(), maplet.getSourceIndex());
239 }
240 return result;
241 }
242
243 /**
244 * Creates a type variable mapping from a domain to a range.
245 *
246 * @param domain
247 * the domain of the mapping
248 * @param range
249 * the range of the mapping
250 * @param indexes
251 * <code>true</code> if the indexes should be compared, <code>false</code> if the names should be compared
252 * @return a possibly empty type variable mapping
253 */
254 private static TypeVariableMaplet[] parametersToSignatures(final ITypeParameter[] domain, final String[] range, final boolean indexes) {
255 Assert.isNotNull(domain);
256 Assert.isNotNull(range);
257
258 final Set<TypeVariableMaplet> set= new HashSet<TypeVariableMaplet>();
259 ITypeParameter source= null;
260 String target= null;
261 String element= null;
262 String signature= null;
263 for (int index= 0; index < domain.length; index++) {
264 source= domain[index];
265 for (int offset= 0; offset < range.length; offset++) {
266 target= range[offset];
267 element= source.getElementName();
268 signature= Signature.toString(target);
269 if (indexes) {
270 if (offset == index)
271 set.add(new TypeVariableMaplet(element, index, signature, offset));
272 } else {
273 if (element.equals(signature))
274 set.add(new TypeVariableMaplet(element, index, signature, offset));
275 }
276 }
277 }
278 final TypeVariableMaplet[] result= new TypeVariableMaplet[set.size()];
279 set.toArray(result);
280 return result;
281 }
282
283 /**
284 * Converts the specified type parameters to type variable names.
285 *
286 * @param parameters
287 * the type parameters to convert.
288 * @return the converted type variable names
289 * @see ITypeParameter#getElementName()
290 */
291 private static String[] parametersToVariables(final ITypeParameter[] parameters) {
292 Assert.isNotNull(parameters);
293
294 String[] result= new String[parameters.length];
295 for (int index= 0; index < parameters.length; index++)
296 result[index]= parameters[index].getElementName();
297
298 return result;
299 }
300
301 /**
302 * Creates a type variable mapping from a domain to a range.
303 *
304 * @param domain
305 * the domain of the mapping
306 * @param range
307 * the range of the mapping
308 * @return a possibly empty type variable mapping
309 */
310 private static TypeVariableMaplet[] signaturesToParameters(final String[] domain, final ITypeParameter[] range) {
311 Assert.isNotNull(domain);
312 Assert.isNotNull(range);
313 Assert.isTrue(domain.length == 0 || domain.length == range.length);
314
315 final List<TypeVariableMaplet> list= new ArrayList<TypeVariableMaplet>();
316 String source= null;
317 String target= null;
318 for (int index= 0; index < domain.length; index++) {
319 source= Signature.toString(domain[index]);
320 target= range[index].getElementName();
321 list.add(new TypeVariableMaplet(source, index, target, index));
322 }
323 final TypeVariableMaplet[] result= new TypeVariableMaplet[list.size()];
324 list.toArray(result);
325 return result;
326 }
327
328 /**
329 * Returns a type variable mapping from a subclass to a superclass.
330 *
331 * @param type
332 * the type representing the subclass class
333 * @return a type variable mapping. The mapping entries consist of simple type variable names.
334 * @throws JavaModelException
335 * if the signature of one of the types involved could not be retrieved
336 */
337 public static TypeVariableMaplet[] subTypeToInheritedType(final IType type) throws JavaModelException {
338 Assert.isNotNull(type);
339
340 final ITypeParameter[] domain= type.getTypeParameters();
341 if (domain.length > 0) {
342 final String signature= type.getSuperclassTypeSignature();
343 if (signature != null) {
344 final String[] range= getVariableSignatures(signature);
345 if (range.length > 0)
346 return parametersToSignatures(domain, range, false);
347 }
348 }
349 return new TypeVariableMaplet[0];
350 }
351
352 /**
353 * Returns a type variable mapping from a subclass to a superclass.
354 *
355 * @param subtype
356 * the type representing the subclass
357 * @param supertype
358 * the type representing the superclass
359 * @return a type variable mapping. The mapping entries consist of simple type variable names.
360 * @throws JavaModelException
361 * if the signature of one of the types involved could not be retrieved
362 */
363 public static TypeVariableMaplet[] subTypeToSuperType(final IType subtype, final IType supertype) throws JavaModelException {
364 Assert.isNotNull(subtype);
365 Assert.isNotNull(supertype);
366
367 final TypeVariableMaplet[] mapping= subTypeToInheritedType(subtype);
368 if (mapping.length > 0) {
369 final ITypeParameter[] range= supertype.getTypeParameters();
370 if (range.length > 0) {
371 final String signature= subtype.getSuperclassTypeSignature();
372 if (signature != null) {
373 final String[] domain= getVariableSignatures(signature);
374 if (domain.length > 0)
375 return composeMappings(mapping, signaturesToParameters(domain, range));
376 }
377 }
378 }
379 return mapping;
380 }
381
382 /**
383 * Returns a type variable mapping from a superclass to a subclass.
384 *
385 * @param supertype
386 * the type representing the superclass
387 * @param subtype
388 * the type representing the subclass
389 * @return a type variable mapping. The mapping entries consist of simple type variable names.
390 * @throws JavaModelException
391 * if the signature of one of the types involved could not be retrieved
392 */
393 public static TypeVariableMaplet[] superTypeToInheritedType(final IType supertype, final IType subtype) throws JavaModelException {
394 Assert.isNotNull(subtype);
395 Assert.isNotNull(supertype);
396
397 final ITypeParameter[] domain= supertype.getTypeParameters();
398 if (domain.length > 0) {
399 final String signature= subtype.getSuperclassTypeSignature();
400 if (signature != null) {
401 final String[] range= getVariableSignatures(signature);
402 if (range.length > 0)
403 return parametersToSignatures(domain, range, true);
404 }
405 }
406 return new TypeVariableMaplet[0];
407 }
408
409 /**
410 * Returns a type variable mapping from a superclass to a subclass.
411 *
412 * @param supertype
413 * the type representing the superclass
414 * @param subtype
415 * the type representing the subclass
416 * @return a type variable mapping. The mapping entries consist of simple type variable names.
417 * @throws JavaModelException
418 * if the signature of one of the types involved could not be retrieved
419 */
420 public static TypeVariableMaplet[] superTypeToSubType(final IType supertype, final IType subtype) throws JavaModelException {
421 Assert.isNotNull(supertype);
422 Assert.isNotNull(subtype);
423
424 return inverseMapping(subTypeToSuperType(subtype, supertype));
425 }
426
427 private TypeVariableUtil() {
428 // Not to be instantiated
429 }
430}