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

(-)dom/org/eclipse/jdt/core/dom/CompilationUnit.java (-4 / +12 lines)
Lines 484-491 Link Here
484
	 * @since 3.0
484
	 * @since 3.0
485
	 */
485
	 */
486
	public int getExtendedStartPosition(ASTNode node) {
486
	public int getExtendedStartPosition(ASTNode node) {
487
		if (this.commentMapper == null) {
487
		if (node == null) {
488
			return -1;
488
			throw new IllegalArgumentException();
489
		}
490
		if (this.commentMapper == null || node.getAST() != getAST()) {
491
			// fall back: use best info available
492
			return node.getStartPosition();
489
		} else {
493
		} else {
490
			return this.commentMapper.getExtendedStartPosition(node);
494
			return this.commentMapper.getExtendedStartPosition(node);
491
		}
495
		}
Lines 504-511 Link Here
504
	 * @since 3.0
508
	 * @since 3.0
505
	 */
509
	 */
506
	public int getExtendedLength(ASTNode node) {
510
	public int getExtendedLength(ASTNode node) {
507
		if (this.commentMapper == null) {
511
		if (node == null) {
508
			return 0;
512
			throw new IllegalArgumentException();
513
		}
514
		if (this.commentMapper == null || node.getAST() != getAST()) {
515
			// fall back: use best info available
516
			return node.getLength();
509
		} else {
517
		} else {
510
			return this.commentMapper.getExtendedLength(node);
518
			return this.commentMapper.getExtendedLength(node);
511
		}
519
		}
(-)dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java (-2 / +17 lines)
Lines 20-25 Link Here
20
20
21
import org.eclipse.jdt.core.dom.SimplePropertyDescriptor;
21
import org.eclipse.jdt.core.dom.SimplePropertyDescriptor;
22
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
22
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
23
import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
23
import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
24
import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
24
import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
25
import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
25
import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
26
import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
Lines 65-73 Link Here
65
	public TextEdit rewriteAST(IDocument document, Map options) {
66
	public TextEdit rewriteAST(IDocument document, Map options) {
66
		TextEdit result = new MultiTextEdit();
67
		TextEdit result = new MultiTextEdit();
67
		
68
		
68
		CompilationUnit rootNode = getRootNode();
69
		final CompilationUnit rootNode = getRootNode();
69
		if (rootNode != null) {
70
		if (rootNode != null) {
70
			ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(document, rootNode, result, this.eventStore, this.nodeStore, options);
71
			TargetSourceRangeComputer xsrComputer = new TargetSourceRangeComputer() {
72
				/** 
73
				 * This implementation of
74
				 * {@link TargetSourceRangeComputer#computeSourceRange(ASTNode)}
75
				 * is specialized to work in the case of internal AST rewriting, where the
76
				 * original AST has been modified from its original form. This means that
77
				 * one cannot trust that the root of the given node is the compilation unit.
78
				 */
79
				public SourceRange computeSourceRange(ASTNode node) {
80
					int extendedStartPosition = rootNode.getExtendedStartPosition(node);
81
					int extendedLength = rootNode.getExtendedLength(node);
82
					return new SourceRange(extendedStartPosition, extendedLength);
83
				}
84
			};
85
			ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(document, rootNode, result, this.eventStore, this.nodeStore, options, xsrComputer);
71
			rootNode.accept(visitor);
86
			rootNode.accept(visitor);
72
		}
87
		}
73
		return result;
88
		return result;
(-)dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java (-1 / +41 lines)
Lines 85-90 Link Here
85
	private final NodeInfoStore nodeStore;
85
	private final NodeInfoStore nodeStore;
86
	
86
	
87
	/**
87
	/**
88
	 * Target source range computer; null means uninitialized;
89
	 * lazy initialized to <code>new TargetSourceRangeComputer()</code>.
90
	 * @since 3.1
91
	 */
92
	private TargetSourceRangeComputer targetSourceRangeComputer = null;
93
	
94
	/**
88
	 * Creates a new instance for describing manipulations of
95
	 * Creates a new instance for describing manipulations of
89
	 * the given AST.
96
	 * the given AST.
90
	 * 
97
	 * 
Lines 140-145 Link Here
140
	 * edits to the given document containing the original source
147
	 * edits to the given document containing the original source
141
	 * code. The document itself is not modified.
148
	 * code. The document itself is not modified.
142
	 * <p>
149
	 * <p>
150
	 * For nodes in the original that are being replaced or deleted,
151
	 * this rewriter computes the adjusted source ranges
152
	 * by calling <code>getTargetSourceRangeComputer().computeSourceRange(node)</code>.
153
	 * </p>
154
	 * <p>
143
	 * Calling this methods does not discard the modifications
155
	 * Calling this methods does not discard the modifications
144
	 * on record. Subsequence modifications are added to the ones
156
	 * on record. Subsequence modifications are added to the ones
145
	 * already on record. If this method is called again later,
157
	 * already on record. If this method is called again later,
Lines 170-176 Link Here
170
			getRewriteEventStore().markMovedNodesRemoved();
182
			getRewriteEventStore().markMovedNodesRemoved();
171
183
172
			CompilationUnit astRoot= (CompilationUnit) rootNode.getRoot();
184
			CompilationUnit astRoot= (CompilationUnit) rootNode.getRoot();
173
			ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(document, astRoot, result, this.eventStore, this.nodeStore, options);
185
			ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(document, astRoot, result, this.eventStore, this.nodeStore, options, getExtendedSourceRangeComputer());
174
			rootNode.accept(visitor); // throws IllegalArgumentException
186
			rootNode.accept(visitor); // throws IllegalArgumentException
175
		}
187
		}
176
		return result;
188
		return result;
Lines 499-504 Link Here
499
	public final ASTNode createMoveTarget(ASTNode node) {
511
	public final ASTNode createMoveTarget(ASTNode node) {
500
		return createTargetNode(node, true);
512
		return createTargetNode(node, true);
501
	}	
513
	}	
514
515
	/**
516
	 * Returns the extended source range computer for this AST rewriter.
517
	 * The default value is a <code>new ExtendedSourceRangeComputer()</code>.
518
	 * 
519
	 * @return an extended source range computer
520
	 * @since 3.1
521
	 */
522
	public final TargetSourceRangeComputer getExtendedSourceRangeComputer() {
523
		if (this.targetSourceRangeComputer == null) {
524
			// lazy initialize
525
			this.targetSourceRangeComputer = new TargetSourceRangeComputer(); 
526
		}
527
		return this.targetSourceRangeComputer;
528
	}
529
	
530
	/**
531
	 * Sets the target source range computer for this AST rewriter.
532
	 * 
533
	 * @param computer a target source range computer,
534
	 * or <code>null</code> to restore the default value of
535
	 * <code>new TargetSourceRangeComputer()</code>
536
	 * @since 3.1
537
	 */
538
	public final void setTargetSourceRangeComputer(TargetSourceRangeComputer computer) {
539
		// if computer==null, rely on lazy init code in getTargetSourceRangeComputer()
540
		this.targetSourceRangeComputer = computer;
541
	}
502
	
542
	
503
	/**
543
	/**
504
	 * Returns a string suitable for debugging purposes (only).
544
	 * Returns a string suitable for debugging purposes (only).
(-)dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java (-4 / +20 lines)
Lines 41-46 Link Here
41
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
41
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
42
42
43
import org.eclipse.jdt.core.dom.*;
43
import org.eclipse.jdt.core.dom.*;
44
import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
44
45
45
import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.BlockContext;
46
import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.BlockContext;
46
import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.NodeMarker;
47
import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.NodeMarker;
Lines 73-83 Link Here
73
	private final ASTRewriteFormatter formatter;
74
	private final ASTRewriteFormatter formatter;
74
	private final NodeInfoStore nodeInfos;
75
	private final NodeInfoStore nodeInfos;
75
	private final CompilationUnit astRoot;
76
	private final CompilationUnit astRoot;
77
	private final TargetSourceRangeComputer extendedSourceRangeComputer;
76
	
78
	
77
	/*
79
	/*
78
	 * Constructor for ASTRewriteAnalyzer.
80
	 * Constructor for ASTRewriteAnalyzer.
79
	 */
81
	 */
80
	public ASTRewriteAnalyzer(IDocument document, CompilationUnit astRoot, TextEdit rootEdit, RewriteEventStore eventStore, NodeInfoStore nodeInfos, Map options) {
82
	public ASTRewriteAnalyzer(IDocument document, CompilationUnit astRoot, TextEdit rootEdit, RewriteEventStore eventStore, NodeInfoStore nodeInfos, Map options, TargetSourceRangeComputer extendedSourceRangeComputer) {
81
		this.astRoot= astRoot;
83
		this.astRoot= astRoot;
82
		this.eventStore= eventStore;
84
		this.eventStore= eventStore;
83
		this.document= document;
85
		this.document= document;
Lines 88-93 Link Here
88
		this.sourceCopyEndNodes= new Stack();
90
		this.sourceCopyEndNodes= new Stack();
89
		
91
		
90
		this.formatter= new ASTRewriteFormatter(nodeInfos, eventStore, options, getLineDelimiter());
92
		this.formatter= new ASTRewriteFormatter(nodeInfos, eventStore, options, getLineDelimiter());
93
		
94
		this.extendedSourceRangeComputer = extendedSourceRangeComputer;
91
	}
95
	}
92
		
96
		
93
	final TokenScanner getScanner() {
97
	final TokenScanner getScanner() {
Lines 103-118 Link Here
103
		return this.document;
107
		return this.document;
104
	}
108
	}
105
	
109
	
110
	/**
111
	 * Returns the extended source range computer for this AST rewriter.
112
	 * 
113
	 * @return an extended source range computer (never null)
114
	 * @since 3.1
115
	 */
116
	private TargetSourceRangeComputer getExtendedSourceRangeComputer() {
117
		return this.extendedSourceRangeComputer;
118
	}
119
	
106
	final int getExtendedOffset(ASTNode node) {
120
	final int getExtendedOffset(ASTNode node) {
107
		return this.astRoot.getExtendedStartPosition(node);
121
		return getExtendedSourceRangeComputer().computeSourceRange(node).getStartPosition();
108
	}
122
	}
109
	
123
	
110
	final int getExtendedLength(ASTNode node) {
124
	final int getExtendedLength(ASTNode node) {
111
		return this.astRoot.getExtendedLength(node);
125
		return getExtendedSourceRangeComputer().computeSourceRange(node).getLength();
112
	}
126
	}
113
	
127
	
114
	final int getExtendedEnd(ASTNode node) {
128
	final int getExtendedEnd(ASTNode node) {
115
		return this.astRoot.getExtendedStartPosition(node) + this.astRoot.getExtendedLength(node);
129
		TargetSourceRangeComputer.SourceRange range =
130
			getExtendedSourceRangeComputer().computeSourceRange(node);
131
		return range.getStartPosition() + range.getLength();
116
	}
132
	}
117
	
133
	
118
	final TextEdit getCopySourceEdit(CopySourceInfo info) {
134
	final TextEdit getCopySourceEdit(CopySourceInfo info) {
(-)dom/org/eclipse/jdt/core/dom/rewrite/TargetSourceRangeComputer.java (+127 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Common Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/cpl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.core.dom.rewrite;
12
13
import org.eclipse.jdt.core.dom.ASTNode;
14
import org.eclipse.jdt.core.dom.CompilationUnit;
15
16
/**
17
 * An object for computing adjusted source ranges for AST nodes
18
 * that are being replaced or deleted.
19
 * <p>
20
 * For example, a refactoring like inline method may choose to replace
21
 * calls to the method but leave intact any comments immediately preceding
22
 * the calls. On the other hand, a refactoring like extract method may choose
23
 * to extract not only the nodes for the selected code but also any
24
 * comments preceding or following them.
25
 * </p>
26
 * <p>
27
 * Clients should subclass if they need to influence the 
28
 * the source range to be affected when replacing or deleting a particular node.
29
 * An instance of the subclass should be registered with
30
 * {@link ASTRewrite#setTargetSourceRangeComputer(TargetSourceRangeComputer)}.
31
 * During a call to {@link ASTRewrite#rewriteAST(org.eclipse.jface.text.IDocument, java.util.Map)},
32
 * the {@link #computeSourceRange(ASTNode)} method on this object will be
33
 * used to compute the source range for a node being deleted or replaced.
34
 * </p>
35
 * 
36
 * @since 3.1
37
 */
38
public class TargetSourceRangeComputer {
39
	
40
	/**
41
	 * Reified source range. Instances are &quot;value&quot; object
42
	 * (cannot be modified).
43
	 * 
44
	 * @since 3.1
45
	 */
46
	public static final class SourceRange {
47
		/**
48
		 * 0-based character index, or <code>-1</code>
49
		 * if no source position information is known.
50
		 */
51
		private int startPosition;
52
		
53
		/**
54
		 * (possibly 0) length, or <code>0</code>
55
		 * if no source position information is known.
56
		 */
57
		private int length;
58
		
59
		/**
60
		 * Creates a new source range.
61
		 * 
62
		 * @param startPosition the 0-based character index, or <code>-1</code>
63
		 *    if no source position information is known
64
		 * @param length the (possibly 0) length, or <code>0</code>
65
		 *    if no source position information is known
66
		 */
67
		public SourceRange(int startPosition, int length) {
68
			this.startPosition = startPosition;
69
			this.length = length;
70
		}
71
		
72
		/**
73
		 * Returns the start position.
74
		 * 
75
		 * @return the 0-based character index, or <code>-1</code>
76
		 *    if no source position information is known
77
		 */
78
		public int getStartPosition() {
79
			return this.startPosition;
80
		}
81
82
		/**
83
		 * Returns the source length.
84
		 * 
85
		 * @return a (possibly 0) length, or <code>0</code>
86
		 *    if no source position information is known
87
		 */
88
		public int getLength() {
89
			return this.length;
90
		}
91
	}
92
93
	/**
94
	 * Creates a new target source range computer.
95
	 */
96
	public TargetSourceRangeComputer() {
97
		// do nothing
98
	}
99
100
	/**
101
	 * Returns the target source range of the given node. Unlike
102
	 * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
103
	 * the extended source range may include comments and whitespace
104
	 * immediately before or after the normal source range for the node.
105
	 * <p>
106
	 * The default implementation uses
107
	 * {@link CompilationUnit#getExtendedStartPosition(ASTNode)}
108
	 * and {@link CompilationUnit#getExtendedLength(ASTNode)}
109
	 * to compute the target source range. Clients may override or
110
	 * extend this method to expand or contract the source range of the
111
	 * given node. The resulting source range must cover at least the
112
	 * original source range of the node.
113
	 * </p>
114
	 * 
115
	 * @param node the node with a known source range in the compilation unit
116
	 * being rewritten
117
	 * @return the exact source range in the compilation unit being rewritten
118
	 * that should be replaced (or deleted)
119
	 */
120
	public SourceRange computeSourceRange(ASTNode node) {
121
		// TODO (Martin) Is it true that this method will only be called on AST nodes that are part of the original tree and have at least a basic source position?
122
		CompilationUnit cu = (CompilationUnit) node.getRoot();
123
		return new SourceRange(
124
				cu.getExtendedStartPosition(node),
125
				cu.getExtendedLength(node));
126
	}
127
}

Return to bug 80839