View | Details | Raw Unified | Return to bug 278496
Collapse All | Expand All

(-)src/org/aspectj/asm/AsmManager.java (-17 / +221 lines)
Lines 83-91 Link Here
83
	// below to the AjState for a compilation and recover it if switching
83
	// below to the AjState for a compilation and recover it if switching
84
	// between projects.
84
	// between projects.
85
	protected IHierarchy hierarchy;
85
	protected IHierarchy hierarchy;
86
	
86
87
	/* Map from String > String - it maps absolute paths for 
87
	/*
88
	 * inpath dirs/jars to workspace relative paths suitable for handle inclusion */
88
	 * Map from String > String - it maps absolute paths for inpath dirs/jars to workspace relative paths suitable for handle
89
	 * inclusion
90
	 */
89
	protected Map inpathMap;
91
	protected Map inpathMap;
90
	private IRelationshipMap mapper;
92
	private IRelationshipMap mapper;
91
	private IElementHandleProvider handleProvider;
93
	private IElementHandleProvider handleProvider;
Lines 654-669 Link Here
654
656
655
	}
657
	}
656
658
657
	private String getTypeNameFromHandle(String handle,Map cache) {
659
	private String getTypeNameFromHandle(String handle, Map cache) {
658
		String typename = (String)cache.get(handle);
660
		String typename = (String) cache.get(handle);
659
		if (typename!=null) {
661
		if (typename != null) {
660
			return typename;
662
			return typename;
661
		}
663
		}
662
		// inpath handle - but for which type?
664
		// inpath handle - but for which type?
663
		// let's do it the slow way, we can optimize this with a cache perhaps
665
		// let's do it the slow way, we can optimize this with a cache perhaps
664
		int hasPackage = handle.indexOf('<');
666
		int hasPackage = handle.indexOf('<');
665
		int typeLocation = handle.indexOf('['); 
667
		int typeLocation = handle.indexOf('[');
666
		if (typeLocation==-1) {
668
		if (typeLocation == -1) {
667
			typeLocation = handle.indexOf('}');
669
			typeLocation = handle.indexOf('}');
668
		}
670
		}
669
		if (typeLocation == -1) {
671
		if (typeLocation == -1) {
Lines 671-685 Link Here
671
			return "";
673
			return "";
672
		}
674
		}
673
		StringBuffer qualifiedTypeNameFromHandle = new StringBuffer();
675
		StringBuffer qualifiedTypeNameFromHandle = new StringBuffer();
674
		if (hasPackage!=-1) {
676
		if (hasPackage != -1) {
675
			qualifiedTypeNameFromHandle.append(handle.substring(hasPackage+1,handle.indexOf('(',hasPackage)));
677
			qualifiedTypeNameFromHandle.append(handle.substring(hasPackage + 1, handle.indexOf('(', hasPackage)));
676
			qualifiedTypeNameFromHandle.append('.');
678
			qualifiedTypeNameFromHandle.append('.');
677
		}
679
		}
678
		qualifiedTypeNameFromHandle.append(handle.substring(typeLocation+1));
680
		qualifiedTypeNameFromHandle.append(handle.substring(typeLocation + 1));
679
		typename = qualifiedTypeNameFromHandle.toString();
681
		typename = qualifiedTypeNameFromHandle.toString();
680
		cache.put(handle,typename);
682
		cache.put(handle, typename);
681
		return typename;
683
		return typename;
682
	}
684
	}
685
683
	/**
686
	/**
684
	 * two kinds of relationships
687
	 * two kinds of relationships
685
	 * 
688
	 * 
Lines 726-732 Link Here
726
			if (isPhantomHandle(hid)) {
729
			if (isPhantomHandle(hid)) {
727
				// inpath handle - but for which type?
730
				// inpath handle - but for which type?
728
				// TODO promote cache for reuse during one whole model update
731
				// TODO promote cache for reuse during one whole model update
729
				if (!getTypeNameFromHandle(hid,handleToTypenameCache).equals(typename)) {
732
				if (!getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
730
					continue;
733
					continue;
731
				}
734
				}
732
			}
735
			}
Lines 805-811 Link Here
805
					// they need removing
808
					// they need removing
806
					for (Iterator targetsIter = targets.iterator(); targetsIter.hasNext();) {
809
					for (Iterator targetsIter = targets.iterator(); targetsIter.hasNext();) {
807
						String targethid = (String) targetsIter.next();
810
						String targethid = (String) targetsIter.next();
808
						if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid,handleToTypenameCache).equals(typename)) {
811
						if (isPhantomHandle(hid) && !getTypeNameFromHandle(hid, handleToTypenameCache).equals(typename)) {
809
							continue;
812
							continue;
810
						}
813
						}
811
						// Does this point to the same type?
814
						// Does this point to the same type?
Lines 910-922 Link Here
910
		}
913
		}
911
		return (type.equals(containingType));
914
		return (type.equals(containingType));
912
	}
915
	}
913
	
916
914
	/**
917
	/**
915
	 * @param handle a JDT like handle, following the form described in AsmRelationshipProvider.findOrFakeUpNode
918
	 * @param handle a JDT like handle, following the form described in AsmRelationshipProvider.findOrFakeUpNode
916
	 * @return true if the handle contains ';' - the char indicating that it is a phantom handle
919
	 * @return true if the handle contains ';' - the char indicating that it is a phantom handle
917
	 */
920
	 */
918
	private boolean isPhantomHandle(String handle) {
921
	private boolean isPhantomHandle(String handle) {
919
		return handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter())!=-1;
922
		return handle.indexOf(HandleProviderDelimiter.PHANTOM.getDelimiter()) != -1;
920
	}
923
	}
921
924
922
	/**
925
	/**
Lines 1307-1313 Link Here
1307
	}
1310
	}
1308
1311
1309
	public String getHandleElementForInpath(String binaryPath) {
1312
	public String getHandleElementForInpath(String binaryPath) {
1310
		return (String)inpathMap.get(new File(binaryPath));
1313
		return (String) inpathMap.get(new File(binaryPath));
1314
	}
1315
1316
	private List pieces = new ArrayList();
1317
1318
	private Object intern(String substring) {
1319
		int lastIdx = -1;
1320
		if ((lastIdx = substring.lastIndexOf('/')) != -1) {
1321
			String pkg = substring.substring(0, lastIdx);
1322
			String type = substring.substring(lastIdx + 1);
1323
			pkg = internOneThing(pkg);
1324
			type = internOneThing(type);
1325
			return new String[] { pkg, type };
1326
		} else {
1327
			return internOneThing(substring);
1328
		}
1311
	}
1329
	}
1312
1330
1331
	private String internOneThing(String substring) {
1332
		// simple name
1333
		for (int p = 0, max = pieces.size(); p < max; p++) {
1334
			String s = (String) pieces.get(p);
1335
			if (s.equals(substring)) {
1336
				return s;
1337
			}
1338
		}
1339
		pieces.add(substring);
1340
		return substring;
1341
	}
1342
1343
	/**
1344
	 * What we can rely on: <br>
1345
	 * - it is a method signature of the form (La/B;Lc/D;)LFoo;<br>
1346
	 * - there are no generics<br>
1347
	 * 
1348
	 * What we must allow for: - may use primitive refs (single chars rather than L)
1349
	 */
1350
/*
1351
	public List compress(String s) {
1352
		int openParen = 0;
1353
		int closeParen = s.indexOf(')');
1354
		int pos = 1;
1355
		List compressed = new ArrayList();
1356
		// do the parens
1357
		while (pos < closeParen) {
1358
			char ch = s.charAt(pos);
1359
			if (ch == 'L') {
1360
				int idx = s.indexOf(';', pos);
1361
				compressed.add(intern(s.substring(pos + 1, idx)));
1362
				pos = idx + 1;
1363
			} else if (ch == '[') {
1364
				int x = pos;
1365
				while (s.charAt(++pos) == '[')
1366
					;
1367
				// now pos will point at something not an array
1368
				compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[
1369
				char ch2 = s.charAt(pos);
1370
				if (ch2 == 'L') {
1371
					int idx = s.indexOf(';', pos);
1372
					compressed.add(intern(s.substring(pos + 1, idx)));
1373
					pos = idx + 1;
1374
				} else if (ch2 == 'T') {
1375
					int idx = s.indexOf(';');
1376
					compressed.add(intern(s.substring(pos, idx + 1))); // should be TT;
1377
					pos = idx + 1;
1378
				} else {
1379
					compressed.add(toCharacter(s.charAt(pos)));
1380
					pos++;
1381
				}
1382
			} else {
1383
				// it is a primitive ref (SVBCZJ)
1384
				compressed.add(toCharacter(ch));
1385
				pos++;
1386
			}
1387
		}
1388
		// do the return type
1389
		pos++;
1390
		char ch = s.charAt(pos);
1391
		if (ch == 'L') {
1392
			int idx = s.indexOf(';', pos);
1393
			compressed.add(intern(s.substring(pos, idx)));
1394
		} else if (ch == '[') {
1395
			int x = pos;
1396
			while (s.charAt(++pos) == '[')
1397
				;
1398
			// now pos will point at something not an array
1399
			compressed.add(intern(s.substring(x, pos))); // intern the [[[[[[
1400
			char ch2 = s.charAt(pos);
1401
			if (ch2 == 'L') {
1402
				int idx = s.indexOf(';', pos);
1403
				compressed.add(intern(s.substring(pos + 1, idx)));
1404
				pos = idx + 1;
1405
			} else if (ch2 == 'T') {
1406
				int idx = s.indexOf(';');
1407
				compressed.add(intern(s.substring(pos, idx + 1))); // should be TT;
1408
				pos = idx + 2;
1409
			} else {
1410
				compressed.add(toCharacter(s.charAt(pos)));
1411
				pos++;
1412
			}
1413
		} else {
1414
			// it is a primitive ref (SVBCZJ)
1415
			compressed.add(new Character(ch));
1416
		}
1417
		return compressed;
1418
1419
		// char delimiter = '/';
1420
		// int pos = -1;
1421
		// List compressed = new ArrayList();
1422
		// int start = 0;
1423
		// while ((pos = s.indexOf(delimiter, start)) != -1) {
1424
		// String part = s.substring(start, pos);
1425
		// int alreadyRecorded = pieces.indexOf(part);
1426
		// if (alreadyRecorded != -1) {
1427
		// compressed.add(new Integer(alreadyRecorded));
1428
		// } else {
1429
		// compressed.add(new Integer(pieces.size()));
1430
		// pieces.add(part);
1431
		// }
1432
		// start = pos + 1;
1433
		// }
1434
		// // last piece
1435
		// String part = s.substring(start, s.length());
1436
		// int alreadyRecorded = pieces.indexOf(part);
1437
		// if (alreadyRecorded != -1) {
1438
		// compressed.add(youkirtyounew Integer(alreadyRecorded));
1439
		// } else {
1440
		// compressed.add(new Integer(pieces.size()));
1441
		// pieces.add(part);
1442
		// }
1443
		// return compressed;
1444
	}
1445
1446
	static final Character charB = new Character('B');
1447
	static final Character charS = new Character('S');
1448
	static final Character charI = new Character('I');
1449
	static final Character charF = new Character('F');
1450
	static final Character charD = new Character('D');
1451
	static final Character charJ = new Character('J');
1452
	static final Character charC = new Character('C');
1453
	static final Character charV = new Character('V');
1454
	static final Character charZ = new Character('Z');
1455
1456
	private Character toCharacter(char ch) {
1457
		switch (ch) {
1458
		case 'B':
1459
			return charB;
1460
		case 'S':
1461
			return charS;
1462
		case 'I':
1463
			return charI;
1464
		case 'F':
1465
			return charF;
1466
		case 'D':
1467
			return charD;
1468
		case 'J':
1469
			return charJ;
1470
		case 'C':
1471
			return charC;
1472
		case 'V':
1473
			return charV;
1474
		case 'Z':
1475
			return charZ;
1476
		default:
1477
			throw new IllegalStateException(new Character(ch).toString());
1478
		}
1479
	}
1480
1481
	public String decompress(List refs, char delimiter) {
1482
		StringBuilder result = new StringBuilder();
1483
		result.append("(");
1484
		for (int i = 0, max = refs.size() - 1; i < max; i++) {
1485
			result.append(unintern(refs.get(i)));
1486
		}
1487
		result.append(")");
1488
		result.append(unintern(refs.get(refs.size() - 1)));
1489
		return result.toString();
1490
	}
1491
1492
	private String unintern(Object o) {
1493
		if (o instanceof Character) {
1494
			return ((Character) o).toString();
1495
		} else if (o instanceof String[]) {
1496
			String[] strings = (String[]) o;
1497
			StringBuilder sb = new StringBuilder();
1498
			sb.append('L');
1499
			sb.append(strings[0]).append('/').append(strings[1]);
1500
			sb.append(';');
1501
			return sb.toString();
1502
		} else { // String
1503
			String so = (String) o;
1504
			if (so.endsWith(";")) {
1505
				// will be TT;
1506
				return so;
1507
			} else {
1508
				StringBuilder sb = new StringBuilder();
1509
				sb.append('L');
1510
				sb.append(so);
1511
				sb.append(';');
1512
				return sb.toString();
1513
			}
1514
		}
1515
	}
1516
	*/
1313
}
1517
}
(-)src/org/aspectj/asm/internal/ProgramElement.java (-12 / +35 lines)
Lines 305-316 Link Here
305
		return s;
305
		return s;
306
	}
306
	}
307
307
308
	public String getBytecodeSignature() {
309
		String s = (String) kvpairs.get("bytecodeSignature");
310
		// if (s==null) return UNDEFINED;
311
		return s;
312
	}
313
314
	public void setBytecodeName(String s) {
308
	public void setBytecodeName(String s) {
315
		if (kvpairs == Collections.EMPTY_MAP)
309
		if (kvpairs == Collections.EMPTY_MAP)
316
			kvpairs = new HashMap();
310
			kvpairs = new HashMap();
Lines 318-326 Link Here
318
	}
312
	}
319
313
320
	public void setBytecodeSignature(String s) {
314
	public void setBytecodeSignature(String s) {
321
		if (kvpairs == Collections.EMPTY_MAP)
315
		initMap();
322
			kvpairs = new HashMap();
316
		// Different kinds of format here. The one worth compressing starts with a '(':
317
		// (La/b/c/D;Le/f/g/G;)Ljava/lang/String;
318
		// maybe want to avoid generics initially.
319
		// boolean worthCompressing = s.charAt(0) == '(' && s.indexOf('<') == -1 && s.indexOf('P') == -1; // starts parentheses and
320
		// no
321
		// // generics
322
		// if (worthCompressing) {
323
		// kvpairs.put("bytecodeSignatureCompressed", asm.compress(s));
324
		// } else {
323
		kvpairs.put("bytecodeSignature", s);
325
		kvpairs.put("bytecodeSignature", s);
326
		// }
327
	}
328
329
	public String getBytecodeSignature() {
330
		String s = (String) kvpairs.get("bytecodeSignature");
331
		// if (s == null) {
332
		// List compressed = (List) kvpairs.get("bytecodeSignatureCompressed");
333
		// if (compressed != null) {
334
		// return asm.decompress(compressed, '/');
335
		// }
336
		// }
337
		// if (s==null) return UNDEFINED;
338
		return s;
339
	}
340
341
	private void initMap() {
342
		if (kvpairs == Collections.EMPTY_MAP) {
343
			kvpairs = new HashMap();
344
		}
324
	}
345
	}
325
346
326
	public String getSourceSignature() {
347
	public String getSourceSignature() {
Lines 549-570 Link Here
549
	}
570
	}
550
571
551
	public String getHandleIdentifier(boolean create) {
572
	public String getHandleIdentifier(boolean create) {
573
		String h = null;
552
		if (null == handle && create) {
574
		if (null == handle && create) {
553
			if (asm == null && name.equals("<build to view structure>")) {
575
			if (asm == null && name.equals("<build to view structure>")) {
554
				handle = "<build to view structure>";
576
				h = "<build to view structure>";
555
			} else {
577
			} else {
556
				try {
578
				try {
557
					handle = asm.getHandleProvider().createHandleIdentifier(this);
579
					h = asm.getHandleProvider().createHandleIdentifier(this);
558
				} catch (ArrayIndexOutOfBoundsException aioobe) {
580
				} catch (ArrayIndexOutOfBoundsException aioobe) {
559
					throw new RuntimeException("AIOOBE whilst building handle for " + this, aioobe);
581
					throw new RuntimeException("AIOOBE whilst building handle for " + this, aioobe);
560
				}
582
				}
561
			}
583
			}
562
		}
584
		}
563
		return handle;
585
		setHandleIdentifier(h);
586
		return h;
564
	}
587
	}
565
588
566
	public void setHandleIdentifier(String handle) {
589
	public void setHandleIdentifier(String handle) {
567
		this.handle = handle;
590
		// this.handle = handle;
568
	}
591
	}
569
592
570
	public List getParameterNames() {
593
	public List getParameterNames() {
(-)src/org/aspectj/asm/internal/JDTLikeHandleProvider.java (-7 / +69 lines)
Lines 31-40 Link Here
31
31
32
	private final AsmManager asm;
32
	private final AsmManager asm;
33
33
34
	// Need to keep our own count of the number of initializers
35
	// because this information cannot be gained from the ipe.
36
	private int initializerCounter = 0;
37
38
	private static final char[] empty = new char[] {};
34
	private static final char[] empty = new char[] {};
39
	private static final char[] countDelim = new char[] { HandleProviderDelimiter.COUNT.getDelimiter() };
35
	private static final char[] countDelim = new char[] { HandleProviderDelimiter.COUNT.getDelimiter() };
40
36
Lines 46-52 Link Here
46
	}
42
	}
47
43
48
	public String createHandleIdentifier(IProgramElement ipe) {
44
	public String createHandleIdentifier(IProgramElement ipe) {
49
50
		// AjBuildManager.setupModel --> top of the tree is either
45
		// AjBuildManager.setupModel --> top of the tree is either
51
		// <root> or the .lst file
46
		// <root> or the .lst file
52
		if (ipe == null || (ipe.getKind().equals(IProgramElement.Kind.FILE_JAVA) && ipe.getName().equals("<root>"))) {
47
		if (ipe == null || (ipe.getKind().equals(IProgramElement.Kind.FILE_JAVA) && ipe.getName().equals("<root>"))) {
Lines 284-290 Link Here
284
				return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
279
				return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
285
			}
280
			}
286
		} else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
281
		} else if (ipe.getKind().equals(IProgramElement.Kind.INITIALIZER)) {
287
			return String.valueOf(++initializerCounter).toCharArray();
282
			// return String.valueOf(++initializerCounter).toCharArray();
283
			// Look at any peer advice
284
			int count = 1;
285
			List kids = ipe.getParent().getChildren();
286
			String ipeSig = ipe.getBytecodeSignature();
287
			// remove return type from the signature - it should not be included in the comparison
288
			int idx = 0;
289
			if (ipeSig != null && ((idx = ipeSig.indexOf(")")) != -1)) {
290
				ipeSig = ipeSig.substring(0, idx);
291
			}
292
			if (ipeSig != null) {
293
				if (ipeSig.indexOf("Lorg/aspectj/lang") != -1) {
294
					if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
295
						ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
296
					}
297
					if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint;")) {
298
						ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint;"));
299
					}
300
					if (ipeSig.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
301
						ipeSig = ipeSig.substring(0, ipeSig.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
302
					}
303
				}
304
			}
305
			for (Iterator iterator = kids.iterator(); iterator.hasNext();) {
306
				IProgramElement object = (IProgramElement) iterator.next();
307
				if (object.equals(ipe)) {
308
					break;
309
				}
310
				if (object.getKind() == ipe.getKind()) {
311
					if (object.getName().equals(ipe.getName())) {
312
						String sig1 = object.getBytecodeSignature();
313
						if (sig1 != null && (idx = sig1.indexOf(")")) != -1) {
314
							sig1 = sig1.substring(0, idx);
315
						}
316
						// this code needs a speed overhaul... and some proper tests
317
						// Two static parts because one may be enclosing jpsp (269522)
318
						if (sig1 != null) {
319
							if (sig1.indexOf("Lorg/aspectj/lang") != -1) {
320
								if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
321
									sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
322
								}
323
								if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint;")) {
324
									sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint;"));
325
								}
326
								if (sig1.endsWith("Lorg/aspectj/lang/JoinPoint$StaticPart;")) {
327
									sig1 = sig1.substring(0, sig1.lastIndexOf("Lorg/aspectj/lang/JoinPoint$StaticPart;"));
328
								}
329
							}
330
						}
331
332
						if (sig1 == null && ipeSig == null || (sig1 != null && sig1.equals(ipeSig))) {
333
							String existingHandle = object.getHandleIdentifier();
334
							int suffixPosition = existingHandle.indexOf('!');
335
							if (suffixPosition != -1) {
336
								count = new Integer(existingHandle.substring(suffixPosition + 1)).intValue() + 1;
337
							} else {
338
								if (count == 1) {
339
									count = 2;
340
								}
341
							}
342
						}
343
					}
344
				}
345
			}
346
			// if (count > 1) {
347
			return new Integer(count).toString().toCharArray();
348
			// return CharOperation.concat(countDelim, new Integer(count).toString().toCharArray());
349
			// }
288
		} else if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
350
		} else if (ipe.getKind().equals(IProgramElement.Kind.CODE)) {
289
			int index = CharOperation.lastIndexOf('!', byteCodeName);
351
			int index = CharOperation.lastIndexOf('!', byteCodeName);
290
			if (index != -1) {
352
			if (index != -1) {
Lines 421-426 Link Here
421
	public void initialize() {
483
	public void initialize() {
422
		// reset the initializer count. This ensures we return the
484
		// reset the initializer count. This ensures we return the
423
		// same handle as JDT for initializers.
485
		// same handle as JDT for initializers.
424
		initializerCounter = 0;
486
		// initializerCounter = 0;
425
	}
487
	}
426
}
488
}
(-)src/org/aspectj/asm/internal/CharOperation.java (+103 lines)
Lines 16-21 Link Here
16
 */
16
 */
17
public class CharOperation {
17
public class CharOperation {
18
18
19
	public static final char[][] NO_CHAR_CHAR = new char[0][];
20
21
	public static final char[] NO_CHAR = new char[0];
22
19
	/**
23
	/**
20
	 * Taken from org.aspectj.org.eclipse.jdt.core.compiler.CharOperation
24
	 * Taken from org.aspectj.org.eclipse.jdt.core.compiler.CharOperation
21
	 */
25
	 */
Lines 34-39 Link Here
34
		return result;
38
		return result;
35
	}
39
	}
36
40
41
	public static final char[][] subarray(char[][] array, int start, int end) {
42
		if (end == -1)
43
			end = array.length;
44
		if (start > end)
45
			return null;
46
		if (start < 0)
47
			return null;
48
		if (end > array.length)
49
			return null;
50
51
		char[][] result = new char[end - start][];
52
		System.arraycopy(array, start, result, 0, end - start);
53
		return result;
54
	}
55
56
	public static final char[][] splitOn(char divider, char[] array) {
57
		int length = array == null ? 0 : array.length;
58
		if (length == 0)
59
			return NO_CHAR_CHAR;
60
61
		int wordCount = 1;
62
		for (int i = 0; i < length; i++)
63
			if (array[i] == divider)
64
				wordCount++;
65
		char[][] split = new char[wordCount][];
66
		int last = 0, currentWord = 0;
67
		for (int i = 0; i < length; i++) {
68
			if (array[i] == divider) {
69
				split[currentWord] = new char[i - last];
70
				System.arraycopy(array, last, split[currentWord++], 0, i - last);
71
				last = i + 1;
72
			}
73
		}
74
		split[currentWord] = new char[length - last];
75
		System.arraycopy(array, last, split[currentWord], 0, length - last);
76
		return split;
77
	}
78
37
	/**
79
	/**
38
	 * Taken from org.aspectj.org.eclipse.jdt.core.compiler.CharOperation
80
	 * Taken from org.aspectj.org.eclipse.jdt.core.compiler.CharOperation
39
	 */
81
	 */
Lines 88-93 Link Here
88
		return true;
130
		return true;
89
	}
131
	}
90
132
133
	final static public String toString(char[][] array) {
134
		char[] result = concatWith(array, '.');
135
		return new String(result);
136
	}
137
138
	public static final char[] concatWith(char[][] array, char separator) {
139
		int length = array == null ? 0 : array.length;
140
		if (length == 0)
141
			return CharOperation.NO_CHAR;
142
143
		int size = length - 1;
144
		int index = length;
145
		while (--index >= 0) {
146
			if (array[index].length == 0)
147
				size--;
148
			else
149
				size += array[index].length;
150
		}
151
		if (size <= 0)
152
			return CharOperation.NO_CHAR;
153
		char[] result = new char[size];
154
		index = length;
155
		while (--index >= 0) {
156
			length = array[index].length;
157
			if (length > 0) {
158
				System.arraycopy(array[index], 0, result, (size -= length), length);
159
				if (--size >= 0)
160
					result[size] = separator;
161
			}
162
		}
163
		return result;
164
	}
165
166
	public static final int hashCode(char[] array) {
167
		int length = array.length;
168
		int hash = length == 0 ? 31 : array[0];
169
		if (length < 8) {
170
			for (int i = length; --i > 0;)
171
				hash = (hash * 31) + array[i];
172
		} else {
173
			// 8 characters is enough to compute a decent hash code, don't waste time examining every character
174
			for (int i = length - 1, last = i > 16 ? i - 16 : 0; i > last; i -= 2)
175
				hash = (hash * 31) + array[i];
176
		}
177
		return hash & 0x7FFFFFFF;
178
	}
179
180
	public static final boolean equals(char[][] first, char[][] second) {
181
		if (first == second)
182
			return true;
183
		if (first == null || second == null)
184
			return false;
185
		if (first.length != second.length)
186
			return false;
187
188
		for (int i = first.length; --i >= 0;)
189
			if (!equals(first[i], second[i]))
190
				return false;
191
		return true;
192
	}
193
91
	/**
194
	/**
92
	 * Taken from org.aspectj.org.eclipse.jdt.core.compiler.CharOperation
195
	 * Taken from org.aspectj.org.eclipse.jdt.core.compiler.CharOperation
93
	 */
196
	 */

Return to bug 278496