Skip to main content
summaryrefslogtreecommitdiffstats
blob: 11339f3957f5a17369fbd5fa2a339d0639345547 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*******************************************************************************
 * Copyright (c) 2005, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.core.internal.utility.jdt;

import java.util.Iterator;
import java.util.List;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.core.utility.jdt.AbstractType;
import org.eclipse.jpt.core.utility.jdt.AnnotationEditFormatter;
import org.eclipse.jpt.core.utility.jdt.Type;
import org.eclipse.jpt.utility.CommandExecutor;

/**
 * Adapt and extend a JDT abstract type.
 */
public abstract class AbstractJDTType
	extends JDTMember
	implements AbstractType
{

	/**
	 * constructor for the compilation unit's primary type
	 */
	protected AbstractJDTType(
			AbstractTypeDeclaration typeDeclaration,
			ICompilationUnit compilationUnit,
			CommandExecutor modifySharedDocumentCommandExecutor) {
		this(typeDeclaration, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
	}

	/**
	 * constructor for the compilation unit's primary type
	 */
	protected AbstractJDTType(
			AbstractTypeDeclaration typeDeclaration,
			ICompilationUnit compilationUnit,
			CommandExecutor modifySharedDocumentCommandExecutor,
			AnnotationEditFormatter annotationEditFormatter) {
		this(null, typeDeclaration, 1, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
	}

	/**
	 * constructor for nested types
	 */
	protected AbstractJDTType(
			Type declaringType,
			AbstractTypeDeclaration typeDeclaration,
			int occurrence,
			ICompilationUnit compilationUnit,
			CommandExecutor modifySharedDocumentCommandExecutor) {
		this(declaringType, typeDeclaration, occurrence, compilationUnit, modifySharedDocumentCommandExecutor, DefaultAnnotationEditFormatter.instance());
	}

	/**
	 * constructor for nested types
	 */
	protected AbstractJDTType(
			Type declaringType,
			AbstractTypeDeclaration typeDeclaration,
			int occurrence,
			ICompilationUnit compilationUnit,
			CommandExecutor modifySharedDocumentCommandExecutor,
			AnnotationEditFormatter annotationEditFormatter) {
		super(declaringType, typeDeclaration.getName().getFullyQualifiedName(), occurrence, compilationUnit, modifySharedDocumentCommandExecutor, annotationEditFormatter);
	}

	/**
	 * constructor for testing
	 */
	protected AbstractJDTType(Type declaringType, String name, int occurrence, ICompilationUnit compilationUnit) {
		super(declaringType, name, occurrence, compilationUnit, CommandExecutor.Default.instance(), DefaultAnnotationEditFormatter.instance());
	}

	@Override
	protected Type getDeclaringType() {
		return (Type) super.getDeclaringType();
	}

	// ********** Member/Type implementation **********
	
	public ITypeBinding getBinding(CompilationUnit astRoot) {
		AbstractTypeDeclaration td = this.getBodyDeclaration(astRoot);
		return (td == null) ? null : td.resolveBinding();
	}

	/**
	 * find the type's body declaration in the specified AST
	 */
	@Override
	public AbstractTypeDeclaration getBodyDeclaration(CompilationUnit astRoot) {
		Type declaringType = this.getDeclaringType();
		if (declaringType == null) {
			return this.getTopLevelTypeDeclaration(astRoot);
		}
		TypeDeclaration typeDeclaration = declaringType.getBodyDeclaration(astRoot);
		// the type declaration can be null when the source is completely hosed
		return (typeDeclaration == null) ? null : this.getNestedTypeDeclaration(typeDeclaration);
	}

	public TextRange getNameTextRange(CompilationUnit astRoot) {
		return new ASTNodeTextRange(this.getBodyDeclaration(astRoot).getName());
	}


	// ********** internal **********

	/**
	 * return the first top-level type in the specified AST with a matching name
	 */
	protected AbstractTypeDeclaration getTopLevelTypeDeclaration(CompilationUnit astRoot) {
		return this.getTypeDeclaration(types(astRoot));
	}

	protected AbstractTypeDeclaration getTypeDeclaration(List<AbstractTypeDeclaration> typeDeclarations) {
		return this.getTypeDeclaration(typeDeclarations.toArray(new AbstractTypeDeclaration[typeDeclarations.size()]));
	}

	/**
	 * Return the nested type declaration with matching name and occurrence within the declaring type
	 */
	protected abstract AbstractTypeDeclaration getNestedTypeDeclaration(TypeDeclaration declaringTypeDeclaration);

	/**
	 * return the type declaration corresponding to the type from the specified
	 * set of type declarations (match name and occurrence).
	 * Only return type or enum declarations
	 */
	protected AbstractTypeDeclaration getTypeDeclaration(AbstractTypeDeclaration[] typeDeclarations) {
		String name = this.getName_();
		int occurrence = this.getOccurrence();
		int count = 0;
		for (AbstractTypeDeclaration typeDeclaration : typeDeclarations) {
			if (typeDeclaration.getName().getFullyQualifiedName().equals(name)) {
				count++;
				if (count == occurrence) {
					return (typeDeclaration.getNodeType() == this.getASTNodeType()) ? typeDeclaration : null;
				}
			}
		}
		// return null if the type is no longer in the source code;
		// this can happen when the context model has not yet
		// been synchronized with the resource model but is still
		// asking for an ASTNode (e.g. during a selection event)
		return null;
	}

	protected abstract int getASTNodeType();

	/**
	 * we only instantiate a single top-level, non-annotation
	 * type per compilation unit (i.e. a class, enum, or interface)
	 */
	// minimize scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected static List<AbstractTypeDeclaration> types(CompilationUnit astRoot) {
		return astRoot.types();
	}

	protected static EnumDeclaration[] getEnums(TypeDeclaration declaringTypeDeclaration) {
		List<BodyDeclaration> bd = bodyDeclarations(declaringTypeDeclaration);
		int typeCount = 0;
		for (Iterator<BodyDeclaration> it = bd.listIterator(); it.hasNext(); ) {
			if (it.next().getNodeType() == ASTNode.ENUM_DECLARATION) {
				typeCount++;
			}
		}
		EnumDeclaration[] memberEnums = new EnumDeclaration[typeCount];
		int next = 0;
		for (Iterator<BodyDeclaration> it = bd.listIterator(); it.hasNext(); ) {
			BodyDeclaration decl = it.next();
			if (decl.getNodeType() == ASTNode.ENUM_DECLARATION) {
				memberEnums[next++] = (EnumDeclaration) decl;
			}
		}
		return memberEnums;
	}

	@SuppressWarnings("unchecked")
	protected static List<BodyDeclaration> bodyDeclarations(TypeDeclaration typeDeclaration) {
		return typeDeclaration.bodyDeclarations();
	}

}

Back to the top