View | Details | Raw Unified | Return to bug 24804 | Differences between
and this patch

Collapse All | Expand All

(-)dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java (-6 / +238 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2011 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 11-16 Link Here
11
package org.eclipse.jdt.internal.core.dom.rewrite;
11
package org.eclipse.jdt.internal.core.dom.rewrite;
12
12
13
import java.util.ArrayList;
13
import java.util.ArrayList;
14
import java.util.Collections;
15
import java.util.Comparator;
14
import java.util.HashMap;
16
import java.util.HashMap;
15
import java.util.HashSet;
17
import java.util.HashSet;
16
import java.util.List;
18
import java.util.List;
Lines 26-33 Link Here
26
import org.eclipse.jdt.core.Signature;
28
import org.eclipse.jdt.core.Signature;
27
import org.eclipse.jdt.core.compiler.CharOperation;
29
import org.eclipse.jdt.core.compiler.CharOperation;
28
import org.eclipse.jdt.core.dom.ASTNode;
30
import org.eclipse.jdt.core.dom.ASTNode;
31
import org.eclipse.jdt.core.dom.Comment;
29
import org.eclipse.jdt.core.dom.CompilationUnit;
32
import org.eclipse.jdt.core.dom.CompilationUnit;
30
import org.eclipse.jdt.core.dom.ImportDeclaration;
33
import org.eclipse.jdt.core.dom.ImportDeclaration;
34
import org.eclipse.jdt.core.dom.LineComment;
31
import org.eclipse.jdt.core.dom.PackageDeclaration;
35
import org.eclipse.jdt.core.dom.PackageDeclaration;
32
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
36
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
33
import org.eclipse.jdt.core.search.IJavaSearchConstants;
37
import org.eclipse.jdt.core.search.IJavaSearchConstants;
Lines 58-63 Link Here
58
	private boolean useContextToFilterImplicitImports;
62
	private boolean useContextToFilterImplicitImports;
59
	private boolean findAmbiguousImports;
63
	private boolean findAmbiguousImports;
60
64
65
	private IRegion[] preserveExistingCommentsRanges;
66
61
	private int flags= 0;
67
	private int flags= 0;
62
68
63
	private static final int F_NEEDS_LEADING_DELIM= 2;
69
	private static final int F_NEEDS_LEADING_DELIM= 2;
Lines 89-94 Link Here
89
		this.replaceRange= evaluateReplaceRange(root);
95
		this.replaceRange= evaluateReplaceRange(root);
90
		if (restoreExistingImports) {
96
		if (restoreExistingImports) {
91
			addExistingImports(root);
97
			addExistingImports(root);
98
		} else {
99
			// collect all existing comments inside imports and concatenate them
100
			this.preserveExistingCommentsRanges = retrieveExistingCommentsInImports(root);
92
		}
101
		}
93
102
94
		PackageEntry[] order= new PackageEntry[importOrder.length];
103
		PackageEntry[] order= new PackageEntry[importOrder.length];
Lines 245-251 Link Here
245
		ImportDeclaration curr= (ImportDeclaration) decls.get(0);
254
		ImportDeclaration curr= (ImportDeclaration) decls.get(0);
246
		int currOffset= curr.getStartPosition();
255
		int currOffset= curr.getStartPosition();
247
		int currLength= curr.getLength();
256
		int currLength= curr.getLength();
257
		int currentExtendedEnd =  root.getExtendedStartPosition(curr) + root.getExtendedLength(curr) - 1;
248
		int currEndLine= root.getLineNumber(currOffset + currLength);
258
		int currEndLine= root.getLineNumber(currOffset + currLength);
259
		List commentList = root.getCommentList();
260
		int numberOfComments = commentList.size();
261
		List commentRegions = null;
249
262
250
		for (int i= 1; i < decls.size(); i++) {
263
		for (int i= 1; i < decls.size(); i++) {
251
			boolean isStatic= curr.isStatic();
264
			boolean isStatic= curr.isStatic();
Lines 261-274 Link Here
261
			int nextLength= next.getLength();
274
			int nextLength= next.getLength();
262
			int nextOffsetLine= root.getLineNumber(nextOffset);
275
			int nextOffsetLine= root.getLineNumber(nextOffset);
263
276
277
			int extendedStart = root.getExtendedStartPosition(next);
278
			int extendedLength = root.getExtendedLength(next);
264
			// if next import is on a different line, modify the end position to the next line begin offset
279
			// if next import is on a different line, modify the end position to the next line begin offset
265
			if (currEndLine < nextOffsetLine) {
280
			if (currEndLine < nextOffsetLine) {
266
				currEndLine++;
281
				currEndLine++;
267
				nextOffset= root.getPosition(currEndLine, 0);
282
				nextOffset= root.getPosition(currEndLine, 0);
268
			}
283
			}
269
			currPackage.add(new ImportDeclEntry(packName.length(), name, isStatic, new Region(currOffset, nextOffset - currOffset)));
284
			// retrieve preceding and trailing comments if any
285
			IRegion rangeBefore = null;
286
			IRegion rangeAfter = null;
287
			if (nextOffset != extendedStart) {
288
				rangeBefore = new Region(extendedStart, extendedStart - nextOffset + 1);
289
			}
290
			if (nextLength != extendedLength) {
291
				rangeAfter = new Region(nextOffset + nextLength, extendedLength - nextLength + 1);
292
			}
293
			// retrieve comments not part of the extended range
294
			if ((nextOffsetLine - currEndLine) > 1) {
295
				// check for comments between the two imports
296
				LineComment comment = root.getAST().newLineComment();
297
				comment.setSourceRange(currentExtendedEnd + 1, 0);
298
				int index = Collections.binarySearch(commentList, comment, new Comparator() {
299
					public int compare(Object o1, Object o2) {
300
						return ((Comment) o1).getStartPosition() - ((Comment) o2).getStartPosition();
301
					}
302
				});
303
				// index = -(insertion point) - 1. 
304
				if (index < 0) {
305
					loop: for (int j = -(index + 1); j < numberOfComments; j++) {
306
						Comment currentComment = (Comment) commentList.get(j);
307
						int commentStartPosition = currentComment.getStartPosition();
308
						int commentLength = currentComment.getLength();
309
						if ((commentStartPosition > currentExtendedEnd)
310
								&& ((commentStartPosition + commentLength - 1) < extendedStart)) {
311
							if (commentRegions == null) {
312
								commentRegions = new ArrayList();
313
							}
314
							commentRegions.add(new Region(commentStartPosition, commentLength));
315
						} else {
316
							break loop;
317
						}
318
					}
319
				}
320
			}
321
			currPackage.add(
322
					new ImportDeclEntry(
323
							packName.length(), 
324
							name, 
325
							isStatic, 
326
							new Region(currOffset, nextOffset - currOffset),
327
							rangeBefore,
328
							rangeAfter));
270
			currOffset= nextOffset;
329
			currOffset= nextOffset;
271
			curr= next;
330
			curr= next;
331
			currentExtendedEnd = extendedLength + extendedStart - 1;
272
332
273
			// add a comment entry for spacing between imports
333
			// add a comment entry for spacing between imports
274
			if (currEndLine < nextOffsetLine) {
334
			if (currEndLine < nextOffsetLine) {
Lines 292-299 Link Here
292
		}
352
		}
293
		int length= this.replaceRange.getOffset() + this.replaceRange.getLength() - curr.getStartPosition();
353
		int length= this.replaceRange.getOffset() + this.replaceRange.getLength() - curr.getStartPosition();
294
		currPackage.add(new ImportDeclEntry(packName.length(), name, isStatic, new Region(curr.getStartPosition(), length)));
354
		currPackage.add(new ImportDeclEntry(packName.length(), name, isStatic, new Region(curr.getStartPosition(), length)));
355
		
356
		if (commentRegions != null) {
357
			this.preserveExistingCommentsRanges = (IRegion[]) commentRegions.toArray(new IRegion[commentRegions.size()]);
358
		}
295
	}
359
	}
296
360
361
	private IRegion[] retrieveExistingCommentsInImports(CompilationUnit root) {
362
		List/*ImportDeclaration*/ decls= root.imports();
363
		if (decls.isEmpty()) {
364
			return null;
365
		}
366
		
367
		List commentList = root.getCommentList();
368
		int numberOfComments = commentList.size();
369
		List regions = null;
370
		int currentExtendedEnd = -1;
371
		int currEndLine= -1;
372
373
		/* for the first comment, we only take the trailing comment if any and the replace range doesn't 
374
		 * include the preceding comment
375
		 */
376
		for (int i= 0; i < decls.size(); i++) {
377
			ImportDeclaration next= (ImportDeclaration) decls.get(i);
378
			int nextOffset= next.getStartPosition();
379
			int nextLength= next.getLength();
380
381
			int extendedStart = root.getExtendedStartPosition(next);
382
			int extendedLength = root.getExtendedLength(next);
383
			int nextOffsetLine= root.getLineNumber(nextOffset);
384
385
			if (nextOffset != extendedStart) {
386
				// preceding comment
387
				int lengthOfPrecedingComment = nextOffset - extendedStart;
388
				if (i != 0) {
389
					if (regions == null) {
390
						regions = new ArrayList();
391
					}
392
					regions.add(new Region(extendedStart, lengthOfPrecedingComment));
393
				}
394
				
395
				if (extendedLength != (nextLength + lengthOfPrecedingComment)) {
396
					// Preceding and trailing comments 
397
					int regionLength = extendedLength - (nextLength + lengthOfPrecedingComment);
398
					if (regions == null) {
399
						regions = new ArrayList();
400
					}
401
					regions.add(new Region(nextOffset + nextLength, regionLength));
402
				}
403
			} else if (nextLength != extendedLength) {
404
				// no extended start - only trailing comment
405
				int regionLength = extendedLength - nextLength;
406
				if (regions == null) {
407
					regions = new ArrayList();
408
				}
409
				regions.add(new Region(nextOffset + nextLength, regionLength));
410
			}
411
			if (i > 0) {
412
				// record comments between the previous comment and the current one that are not part
413
				// of any comment extended range.
414
				if ((nextOffsetLine - currEndLine) > 1) {
415
					// check for comments between the two imports
416
					LineComment comment = root.getAST().newLineComment();
417
					comment.setSourceRange(currentExtendedEnd + 1, 0);
418
					int index = Collections.binarySearch(commentList, comment, new Comparator() {
419
						public int compare(Object o1, Object o2) {
420
							return ((Comment) o1).getStartPosition() - ((Comment) o2).getStartPosition();
421
						}
422
					});
423
					// index = -(insertion point) - 1. 
424
					if (index < 0) {
425
						loop: for (int j = -(index + 1); j < numberOfComments; j++) {
426
							Comment currentComment = (Comment) commentList.get(j);
427
							int commentStartPosition = currentComment.getStartPosition();
428
							int commentLength = currentComment.getLength();
429
							if ((commentStartPosition > currentExtendedEnd)
430
									&& ((commentStartPosition + commentLength - 1) < extendedStart)) {
431
								if (regions == null) {
432
									regions = new ArrayList();
433
								}
434
								regions.add(new Region(commentStartPosition, commentLength));
435
							} else {
436
								break loop;
437
							}
438
						}
439
					}
440
				}
441
			}
442
			currentExtendedEnd = extendedStart + extendedLength - 1;
443
			currEndLine = root.getLineNumber(currentExtendedEnd);
444
		}
445
		if (regions == null) {
446
			return null;
447
		}
448
		return (IRegion[]) regions.toArray(new IRegion[regions.size()]);
449
	}
297
	/**
450
	/**
298
	 * Specifies that implicit imports (for types in <code>java.lang</code>, types in the same package as the rewrite
451
	 * Specifies that implicit imports (for types in <code>java.lang</code>, types in the same package as the rewrite
299
	 * compilation unit and types in the compilation unit's main type) should not be created, except if necessary to
452
	 * compilation unit and types in the compilation unit's main type) should not be created, except if necessary to
Lines 550-555 Link Here
550
					}
703
					}
551
				}
704
				}
552
			}
705
			}
706
			// concatenate existing comments inside the imports
707
			
553
			return new Region(startPos, endPos - startPos);
708
			return new Region(startPos, endPos - startPos);
554
		} else {
709
		} else {
555
			int start= getPackageStatementEndPos(root);
710
			int start= getPackageStatementEndPos(root);
Lines 617-623 Link Here
617
772
618
				boolean doStarImport= pack.hasStarImport(threshold, onDemandConflicts);
773
				boolean doStarImport= pack.hasStarImport(threshold, onDemandConflicts);
619
				if (doStarImport && (pack.find("*") == null)) { //$NON-NLS-1$
774
				if (doStarImport && (pack.find("*") == null)) { //$NON-NLS-1$
620
					String[] imports = getNewImportStrings(pack, isStatic, lineDelim);
775
					String[] imports = getNewImportStrings(buffer, pack, isStatic, lineDelim);
621
					for (int j = 0, max = imports.length; j < max; j++) {
776
					for (int j = 0, max = imports.length; j < max; j++) {
622
						stringsToInsert.add(imports[j]);
777
						stringsToInsert.add(imports[j]);
623
					}
778
					}
Lines 648-654 Link Here
648
					} else if (doStarImport && !currDecl.isOnDemand()) {
803
					} else if (doStarImport && !currDecl.isOnDemand()) {
649
						String simpleName = currDecl.getTypeQualifiedName();
804
						String simpleName = currDecl.getTypeQualifiedName();
650
						if (simpleName.indexOf('.') != -1) {
805
						if (simpleName.indexOf('.') != -1) {
651
							String str= getNewImportString(currDecl.getElementName(), isStatic, lineDelim);
806
							IRegion rangeBefore = currDecl.getPrecedingCommentRange();
807
							if (rangeBefore != null) {
808
								stringsToInsert.add(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength()));
809
							}
810
							IRegion rangeAfter = currDecl.getTrailingCommentRange();
811
							String trailingComment = null;
812
							if (rangeAfter != null) {
813
								trailingComment = buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength());
814
							}
815
							String str= getNewImportString(currDecl.getElementName(), isStatic, trailingComment, lineDelim);
652
							if (stringsToInsert.indexOf(str) == -1) {
816
							if (stringsToInsert.indexOf(str) == -1) {
653
								stringsToInsert.add(str);
817
								stringsToInsert.add(str);
654
							}
818
							}
Lines 657-662 Link Here
657
				}
821
				}
658
			}
822
			}
659
823
824
			// insert back all existing imports comments since existing imports were not preserved
825
			if (this.preserveExistingCommentsRanges != null) {
826
				for (int i = 0, max = this.preserveExistingCommentsRanges.length; i < max; i++) {
827
					IRegion region = this.preserveExistingCommentsRanges[i];
828
					String text = buffer.getText(region.getOffset(), region.getLength());
829
					if (!text.endsWith(lineDelim)) {
830
						text += lineDelim;
831
					}
832
					stringsToInsert.add(text);
833
				}
834
			}
660
			int end= importsStart + importsLen;
835
			int end= importsStart + importsLen;
661
			removeAndInsertNew(buffer, currPos, end, stringsToInsert, resEdit);
836
			removeAndInsertNew(buffer, currPos, end, stringsToInsert, resEdit);
662
837
Lines 787-792 Link Here
787
	}
962
	}
788
963
789
	private String getNewImportString(String importName, boolean isStatic, String lineDelim) {
964
	private String getNewImportString(String importName, boolean isStatic, String lineDelim) {
965
		return getNewImportString(importName, isStatic, null, lineDelim);
966
	}
967
	
968
	private String getNewImportString(String importName, boolean isStatic, String trailingComment, String lineDelim) {
790
		StringBuffer buf= new StringBuffer();
969
		StringBuffer buf= new StringBuffer();
791
		buf.append("import "); //$NON-NLS-1$
970
		buf.append("import "); //$NON-NLS-1$
792
		if (isStatic) {
971
		if (isStatic) {
Lines 795-800 Link Here
795
		buf.append(importName);
974
		buf.append(importName);
796
		if (insertSpaceBeforeSemicolon()) buf.append(' ');
975
		if (insertSpaceBeforeSemicolon()) buf.append(' ');
797
		buf.append(';');
976
		buf.append(';');
977
		if (trailingComment != null) {
978
			buf.append(trailingComment);
979
		}
798
		buf.append(lineDelim);
980
		buf.append(lineDelim);
799
981
800
		if (isStatic) {
982
		if (isStatic) {
Lines 805-826 Link Here
805
		return buf.toString();
987
		return buf.toString();
806
	}
988
	}
807
	
989
	
808
	private String[] getNewImportStrings(PackageEntry packageEntry, boolean isStatic, String lineDelim) {
990
	private String[] getNewImportStrings(IBuffer buffer, PackageEntry packageEntry, boolean isStatic, String lineDelim) {
809
		boolean isStarImportAdded = false;
991
		boolean isStarImportAdded = false;
810
		List allImports = new ArrayList();
992
		List allImports = new ArrayList();
811
		int nImports = packageEntry.getNumberOfImports();
993
		int nImports = packageEntry.getNumberOfImports();
994
		StringBuffer allComments = null;
812
		for (int i= 0; i < nImports; i++) {
995
		for (int i= 0; i < nImports; i++) {
813
			ImportDeclEntry curr= packageEntry.getImportAt(i);
996
			ImportDeclEntry curr= packageEntry.getImportAt(i);
814
			String simpleName = curr.getTypeQualifiedName();
997
			String simpleName = curr.getTypeQualifiedName();
815
			if (simpleName.indexOf('.') != -1) {
998
			if (simpleName.indexOf('.') != -1) {
816
				// member type imports - we preserve it
999
				// member type imports - we preserve it
817
				allImports.add(getNewImportString(curr.getElementName(), isStatic, lineDelim));
1000
				IRegion rangeBefore = curr.getPrecedingCommentRange();
1001
				if (rangeBefore != null) {
1002
					allImports.add(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength()));
1003
				}
1004
				IRegion rangeAfter = curr.getTrailingCommentRange();
1005
				String trailingComment = null;
1006
				if (rangeAfter != null) {
1007
					trailingComment = buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength());
1008
				}
1009
				allImports.add(getNewImportString(curr.getElementName(), isStatic, trailingComment, lineDelim));
818
			} else if (!isStarImportAdded) {
1010
			} else if (!isStarImportAdded) {
819
				String starImportString= packageEntry.getName() + ".*"; //$NON-NLS-1$
1011
				String starImportString= packageEntry.getName() + ".*"; //$NON-NLS-1$
820
				allImports.add(getNewImportString(starImportString, isStatic, lineDelim));
1012
				allImports.add(getNewImportString(starImportString, isStatic, lineDelim));
821
				isStarImportAdded = true;
1013
				isStarImportAdded = true;
1014
			} else {
1015
				// collect all comments
1016
				IRegion rangeBefore = curr.getPrecedingCommentRange();
1017
				if (rangeBefore != null) {
1018
					if (allComments == null) {
1019
						allComments = new StringBuffer();
1020
					}
1021
					allComments.append(buffer.getText(rangeBefore.getOffset(), rangeBefore.getLength())).append(lineDelim);
1022
				}
1023
				IRegion rangeAfter = curr.getTrailingCommentRange();
1024
				if (rangeAfter != null) {
1025
					if (allComments == null) {
1026
						allComments = new StringBuffer();
1027
					}
1028
					allComments.append(buffer.getText(rangeAfter.getOffset(), rangeAfter.getLength())).append(lineDelim);
1029
				}
822
			}
1030
			}
823
		}
1031
		}
1032
		if (allComments != null) {
1033
			allImports.add(0, String.valueOf(allComments));
1034
		}
824
		return (String[]) allImports.toArray(new String[allImports.size()]);
1035
		return (String[]) allImports.toArray(new String[allImports.size()]);
825
	}
1036
	}
826
1037
Lines 879-884 Link Here
879
		private IRegion sourceRange;
1090
		private IRegion sourceRange;
880
		private final boolean isStatic;
1091
		private final boolean isStatic;
881
		private int containerNameLength;
1092
		private int containerNameLength;
1093
		private IRegion precedingCommentRange;
1094
		private IRegion trailingCommentRange;
1095
1096
		public ImportDeclEntry(
1097
				int containerNameLength,
1098
				String elementName,
1099
				boolean isStatic,
1100
				IRegion sourceRange,
1101
				IRegion precedingCommentRange,
1102
				IRegion trailingCommentRange) {
1103
			this(containerNameLength, elementName, isStatic, sourceRange);
1104
			this.precedingCommentRange = precedingCommentRange;
1105
			this.trailingCommentRange = trailingCommentRange;
1106
		}
882
1107
883
		public ImportDeclEntry(int containerNameLength, String elementName, boolean isStatic, IRegion sourceRange) {
1108
		public ImportDeclEntry(int containerNameLength, String elementName, boolean isStatic, IRegion sourceRange) {
884
			this.elementName= elementName;
1109
			this.elementName= elementName;
Lines 929-935 Link Here
929
		public IRegion getSourceRange() {
1154
		public IRegion getSourceRange() {
930
			return this.sourceRange;
1155
			return this.sourceRange;
931
		}
1156
		}
1157
		
1158
		public IRegion getPrecedingCommentRange() {
1159
			return this.precedingCommentRange;
1160
		}
932
1161
1162
		public IRegion getTrailingCommentRange() {
1163
			return this.trailingCommentRange;
1164
		}
933
	}
1165
	}
934
1166
935
	/*
1167
	/*

Return to bug 24804