001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
011:
012: import org.eclipse.jdt.core.compiler.CharOperation;
013: import org.eclipse.jdt.internal.compiler.ASTVisitor;
014: import org.eclipse.jdt.internal.compiler.impl.Constant;
015: import org.eclipse.jdt.internal.compiler.lookup.*;
016:
017: public class JavadocAllocationExpression extends AllocationExpression {
018:
019: public int tagSourceStart, tagSourceEnd;
020: public int tagValue, memberStart;
021: public char[][] qualification;
022:
023: public JavadocAllocationExpression(int start, int end) {
024: this .sourceStart = start;
025: this .sourceEnd = end;
026: this .bits |= InsideJavadoc;
027: }
028:
029: public JavadocAllocationExpression(long pos) {
030: this ((int) (pos >>> 32), (int) pos);
031: }
032:
033: TypeBinding internalResolveType(Scope scope) {
034:
035: // Propagate the type checking to the arguments, and check if the constructor is defined.
036: this .constant = Constant.NotAConstant;
037: if (this .type == null) {
038: this .resolvedType = scope.enclosingSourceType();
039: } else if (scope.kind == Scope.CLASS_SCOPE) {
040: this .resolvedType = this .type
041: .resolveType((ClassScope) scope);
042: } else {
043: this .resolvedType = this .type.resolveType(
044: (BlockScope) scope, true /* check bounds*/);
045: }
046:
047: // buffering the arguments' types
048: TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
049: boolean hasTypeVarArgs = false;
050: if (this .arguments != null) {
051: boolean argHasError = false;
052: int length = this .arguments.length;
053: argumentTypes = new TypeBinding[length];
054: for (int i = 0; i < length; i++) {
055: Expression argument = this .arguments[i];
056: if (scope.kind == Scope.CLASS_SCOPE) {
057: argumentTypes[i] = argument
058: .resolveType((ClassScope) scope);
059: } else {
060: argumentTypes[i] = argument
061: .resolveType((BlockScope) scope);
062: }
063: if (argumentTypes[i] == null) {
064: argHasError = true;
065: } else if (!hasTypeVarArgs) {
066: hasTypeVarArgs = argumentTypes[i].isTypeVariable();
067: }
068: }
069: if (argHasError) {
070: return null;
071: }
072: }
073:
074: // check resolved type
075: if (this .resolvedType == null) {
076: return null;
077: }
078: this .resolvedType = scope.environment().convertToRawType(
079: this .type.resolvedType);
080: SourceTypeBinding enclosingType = scope.enclosingSourceType();
081: if (enclosingType == null ? false : enclosingType
082: .isCompatibleWith(this .resolvedType)) {
083: this .bits |= ASTNode.SuperAccess;
084: }
085:
086: ReferenceBinding allocationType = (ReferenceBinding) this .resolvedType;
087: this .binding = scope.getConstructor(allocationType,
088: argumentTypes, this );
089: if (!this .binding.isValidBinding()) {
090: ReferenceBinding enclosingTypeBinding = allocationType;
091: MethodBinding contructorBinding = this .binding;
092: while (!contructorBinding.isValidBinding()
093: && (enclosingTypeBinding.isMemberType() || enclosingTypeBinding
094: .isLocalType())) {
095: enclosingTypeBinding = enclosingTypeBinding
096: .enclosingType();
097: contructorBinding = scope.getConstructor(
098: enclosingTypeBinding, argumentTypes, this );
099: }
100: if (contructorBinding.isValidBinding()) {
101: this .binding = contructorBinding;
102: }
103: }
104: if (!this .binding.isValidBinding()) {
105: // First try to search a method instead
106: MethodBinding methodBinding = scope.getMethod(
107: this .resolvedType, this .resolvedType.sourceName(),
108: argumentTypes, this );
109: if (methodBinding.isValidBinding()) {
110: this .binding = methodBinding;
111: } else {
112: if (this .binding.declaringClass == null) {
113: this .binding.declaringClass = allocationType;
114: }
115: scope.problemReporter().javadocInvalidConstructor(this ,
116: this .binding, scope.getDeclarationModifiers());
117: }
118: return this .resolvedType;
119: } else if (binding.isVarargs()) {
120: int length = argumentTypes.length;
121: if (!(binding.parameters.length == length && argumentTypes[length - 1]
122: .isArrayType())) {
123: MethodBinding problem = new ProblemMethodBinding(
124: this .binding, this .binding.selector,
125: argumentTypes, ProblemReasons.NotFound);
126: scope.problemReporter().javadocInvalidConstructor(this ,
127: problem, scope.getDeclarationModifiers());
128: }
129: } else if (hasTypeVarArgs) {
130: MethodBinding problem = new ProblemMethodBinding(
131: this .binding, this .binding.selector, argumentTypes,
132: ProblemReasons.NotFound);
133: scope.problemReporter().javadocInvalidConstructor(this ,
134: problem, scope.getDeclarationModifiers());
135: } else if (this .binding instanceof ParameterizedMethodBinding) {
136: ParameterizedMethodBinding paramMethodBinding = (ParameterizedMethodBinding) this .binding;
137: if (paramMethodBinding.hasSubstitutedParameters()) {
138: int length = argumentTypes.length;
139: for (int i = 0; i < length; i++) {
140: if (paramMethodBinding.parameters[i] != argumentTypes[i]
141: && paramMethodBinding.parameters[i]
142: .erasure() != argumentTypes[i]
143: .erasure()) {
144: MethodBinding problem = new ProblemMethodBinding(
145: this .binding, this .binding.selector,
146: argumentTypes, ProblemReasons.NotFound);
147: scope
148: .problemReporter()
149: .javadocInvalidConstructor(this ,
150: problem,
151: scope.getDeclarationModifiers());
152: break;
153: }
154: }
155: }
156: } else if (this .resolvedType.isMemberType()) {
157: int length = qualification.length;
158: if (length > 1) { // accept qualified member class constructor reference => see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=103304
159: ReferenceBinding enclosingTypeBinding = allocationType;
160: if (type instanceof JavadocQualifiedTypeReference
161: && ((JavadocQualifiedTypeReference) type).tokens.length != length) {
162: scope.problemReporter()
163: .javadocInvalidMemberTypeQualification(
164: this .memberStart + 1,
165: this .sourceEnd,
166: scope.getDeclarationModifiers());
167: } else {
168: int idx = length;
169: while (idx > 0
170: && CharOperation.equals(
171: qualification[--idx],
172: enclosingTypeBinding.sourceName)
173: && (enclosingTypeBinding = enclosingTypeBinding
174: .enclosingType()) != null) {
175: // verify that each qualification token matches enclosing types
176: }
177: if (idx > 0 || enclosingTypeBinding != null) {
178: scope
179: .problemReporter()
180: .javadocInvalidMemberTypeQualification(
181: this .memberStart + 1,
182: this .sourceEnd,
183: scope.getDeclarationModifiers());
184: }
185: }
186: }
187: }
188: if (isMethodUseDeprecated(this .binding, scope, true)) {
189: scope.problemReporter()
190: .javadocDeprecatedMethod(this .binding, this ,
191: scope.getDeclarationModifiers());
192: }
193: return allocationType;
194: }
195:
196: public boolean isSuperAccess() {
197: return (this .bits & ASTNode.SuperAccess) != 0;
198: }
199:
200: public TypeBinding resolveType(BlockScope scope) {
201: return internalResolveType(scope);
202: }
203:
204: public TypeBinding resolveType(ClassScope scope) {
205: return internalResolveType(scope);
206: }
207:
208: public void traverse(ASTVisitor visitor, BlockScope scope) {
209: if (visitor.visit(this , scope)) {
210: if (this .typeArguments != null) {
211: for (int i = 0, typeArgumentsLength = this .typeArguments.length; i < typeArgumentsLength; i++) {
212: this .typeArguments[i].traverse(visitor, scope);
213: }
214: }
215: if (this .type != null) { // enum constant scenario
216: this .type.traverse(visitor, scope);
217: }
218: if (this .arguments != null) {
219: for (int i = 0, argumentsLength = this .arguments.length; i < argumentsLength; i++)
220: this .arguments[i].traverse(visitor, scope);
221: }
222: }
223: visitor.endVisit(this , scope);
224: }
225:
226: public void traverse(ASTVisitor visitor, ClassScope scope) {
227: if (visitor.visit(this , scope)) {
228: if (this .typeArguments != null) {
229: for (int i = 0, typeArgumentsLength = this .typeArguments.length; i < typeArgumentsLength; i++) {
230: this .typeArguments[i].traverse(visitor, scope);
231: }
232: }
233: if (this .type != null) { // enum constant scenario
234: this .type.traverse(visitor, scope);
235: }
236: if (this .arguments != null) {
237: for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++)
238: this.arguments[i].traverse(visitor, scope);
239: }
240: }
241: visitor.endVisit(this, scope);
242: }
243: }
|