KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > dom > fragments > ASTFragmentFactory


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.dom.fragments;
12
13 import org.eclipse.jdt.core.ICompilationUnit;
14 import org.eclipse.jdt.core.JavaModelException;
15 import org.eclipse.jdt.core.dom.ASTNode;
16 import org.eclipse.jdt.core.dom.Expression;
17 import org.eclipse.jdt.core.dom.InfixExpression;
18
19 import org.eclipse.jdt.internal.corext.Assert;
20 import org.eclipse.jdt.internal.corext.SourceRange;
21 import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor;
22 import org.eclipse.jdt.internal.corext.dom.Selection;
23 import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
24
25 /**
26  * Creates various differing kinds of IASTFragments, all through
27  * a very narrow interface. The kind of IASTFragment produced will depend
28  * on properties of the parameters supplied to the factory methods, such
29  * as the types and characteristics of AST nodes, or the location of
30  * source ranges.
31  *
32  * In general, the client will not be aware of exactly what kind of
33  * fragment is obtained from these methods. Beyond the functionality
34  * provided by the IASTFragment interface, the client can know, however,
35  * based on the parameters passed, some things about the created fragment.
36  * See the documentation of the factory methods.
37  *
38  * @see IASTFragment
39  *
40  */

41 public class ASTFragmentFactory {
42
43     // Factory Methods: /////////////////////////////////////////////////////////////////////////
44

45     /**
46      * Creates and returns a fragment representing the entire subtree
47      * rooted at <code>node</code>. It is not true in general that
48      * the node to which the produced IASTFragment maps (see {@link org.eclipse.jdt.internal.corext.dom.fragments.IASTFragment IASTFragment})
49      * will be <code>node</code>.
50      *
51      * XXX: more doc (current assertions about input vs. output)
52      */

53     public static IASTFragment createFragmentForFullSubtree(ASTNode node) {
54         IASTFragment result= FragmentForFullSubtreeFactory.createFragmentFor(node);
55         Assert.isNotNull(result);
56         return result;
57     }
58     
59     /**
60      * If possible, this method creates a fragment whose source code
61      * range is <code>range</code> within compilation unit <code>cu</code>,
62      * and which resides somewhere within the subtree identified by
63      * <code>scope</code>.
64      *
65      * XXX: more doc (current assertions about input vs. output)
66      *
67      * @param range The source range which the create fragment must have.
68      * @param scope A node identifying the AST subtree in which the fragment must lie.
69      * @param cu The compilation unit to which the source range applies, and to which the AST corresponds.
70      * @return IASTFragment A fragment whose source range is <code>range</code> within
71      * compilation unit <code>cu</code>, residing somewhere within the
72      * AST subtree identified by <code>scope</code>.
73      * @throws JavaModelException
74      */

75     public static IASTFragment createFragmentForSourceRange(SourceRange range, ASTNode scope, ICompilationUnit cu) throws JavaModelException {
76         SelectionAnalyzer sa= new SelectionAnalyzer(Selection.createFromStartLength(range.getOffset(), range.getLength()), false);
77         scope.accept(sa);
78
79         if (isSingleNodeSelected(sa, range, cu))
80             return ASTFragmentFactory.createFragmentForFullSubtree(sa.getFirstSelectedNode());
81         if (isEmptySelectionCoveredByANode(range, sa))
82             return ASTFragmentFactory.createFragmentForFullSubtree(sa.getLastCoveringNode());
83         return ASTFragmentFactory.createFragmentForSubPartBySourceRange(sa.getLastCoveringNode(), range, cu);
84     }
85
86     /////////////////////////////////////////////////////////////////////////////////////////////////////
87

88     
89     private static boolean isEmptySelectionCoveredByANode(SourceRange range, SelectionAnalyzer sa) {
90         return range.getLength() == 0 && sa.getFirstSelectedNode() == null && sa.getLastCoveringNode() != null;
91     }
92
93     private static boolean isSingleNodeSelected(SelectionAnalyzer sa, SourceRange range, ICompilationUnit cu) throws JavaModelException {
94         return sa.getSelectedNodes().length == 1 && !rangeIncludesNonWhitespaceOutsideNode(range, sa.getFirstSelectedNode(), cu);
95     }
96     private static boolean rangeIncludesNonWhitespaceOutsideNode(SourceRange range, ASTNode node, ICompilationUnit cu) throws JavaModelException {
97         return Util.rangeIncludesNonWhitespaceOutsideRange(range, new SourceRange(node), cu.getBuffer());
98     }
99     
100
101     /**
102      * Returns <code>null</code> if the indices, taken with respect to
103      * the node, do not correspond to a valid node-sub-part
104      * fragment.
105      */

106     private static IASTFragment createFragmentForSubPartBySourceRange(ASTNode node, SourceRange range, ICompilationUnit cu) throws JavaModelException {
107         return FragmentForSubPartBySourceRangeFactory.createFragmentFor(node, range, cu);
108     }
109         
110     private static class FragmentForFullSubtreeFactory extends FragmentFactory {
111         public static IASTFragment createFragmentFor(ASTNode node) {
112             return new FragmentForFullSubtreeFactory().createFragment(node);
113         }
114
115         public boolean visit(InfixExpression node) {
116             /* Try creating an associative infix expression fragment
117             /* for the full subtree. If this is not applicable,
118              * try something more generic.
119              */

120             IASTFragment fragment= AssociativeInfixExpressionFragment.createFragmentForFullSubtree(node);
121             if(fragment == null)
122                 return visit((Expression) node);
123             
124             setFragment(fragment);
125             return false;
126         }
127         public boolean visit(Expression node) {
128             setFragment(new SimpleExpressionFragment(node));
129             return false;
130         }
131         public boolean visit(ASTNode node) {
132             setFragment(new SimpleFragment(node));
133             return false;
134         }
135     }
136     private static class FragmentForSubPartBySourceRangeFactory extends FragmentFactory {
137         private SourceRange fRange;
138         private ICompilationUnit fCu;
139         
140         private JavaModelException javaModelException= null;
141         
142         public static IASTFragment createFragmentFor(ASTNode node, SourceRange range, ICompilationUnit cu) throws JavaModelException {
143             return new FragmentForSubPartBySourceRangeFactory().createFragment(node, range, cu);
144         }
145         
146         public boolean visit(InfixExpression node) {
147             try {
148                 setFragment(createInfixExpressionSubPartFragmentBySourceRange(node, fRange, fCu));
149             } catch(JavaModelException e) {
150                 javaModelException= e;
151             }
152             return false;
153         }
154         
155         public boolean visit(ASTNode node) {
156             //let fragment be null
157
return false;
158         }
159         
160         protected IASTFragment createFragment(ASTNode node, SourceRange range, ICompilationUnit cu) throws JavaModelException {
161             fRange= range;
162             fCu= cu;
163             IASTFragment result= createFragment(node);
164             if(javaModelException != null)
165                 throw javaModelException;
166             return result;
167         }
168         
169         private static IExpressionFragment createInfixExpressionSubPartFragmentBySourceRange(InfixExpression node, SourceRange range, ICompilationUnit cu) throws JavaModelException {
170             return AssociativeInfixExpressionFragment.createSubPartFragmentBySourceRange(node, range, cu);
171         }
172     }
173     private static abstract class FragmentFactory extends HierarchicalASTVisitor {
174         private IASTFragment fFragment;
175         
176         protected IASTFragment createFragment(ASTNode node) {
177             fFragment= null;
178             node.accept(this);
179             return fFragment;
180         }
181         
182         protected final IASTFragment getFragment() {
183             return fFragment;
184         }
185         protected final void setFragment(IASTFragment fragment) {
186             Assert.isTrue(!isFragmentSet());
187             fFragment= fragment;
188         }
189         protected final void clearFragment() {
190             fFragment= null;
191         }
192         protected final boolean isFragmentSet() {
193             return getFragment() != null;
194         }
195     }
196 }
197
Popular Tags