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 Argument extends LocalDeclaration {
018:
019: // prefix for setter method (to recognize special hiding argument)
020: private final static char[] SET = "set".toCharArray(); //$NON-NLS-1$
021:
022: public Argument(char[] name, long posNom, TypeReference tr,
023: int modifiers) {
024:
025: super (name, (int) (posNom >>> 32), (int) posNom);
026: this .declarationSourceEnd = (int) posNom;
027: this .modifiers = modifiers;
028: type = tr;
029: this .bits |= IsLocalDeclarationReachable;
030: }
031:
032: public void bind(MethodScope scope, TypeBinding typeBinding,
033: boolean used) {
034:
035: // record the resolved type into the type reference
036: Binding existingVariable = scope
037: .getBinding(name, Binding.VARIABLE, this , false /*do not resolve hidden field*/);
038: if (existingVariable != null
039: && existingVariable.isValidBinding()) {
040: if (existingVariable instanceof LocalVariableBinding
041: && this .hiddenVariableDepth == 0) {
042: scope.problemReporter().redefineArgument(this );
043: } else {
044: boolean isSpecialArgument = false;
045: if (existingVariable instanceof FieldBinding) {
046: if (scope.isInsideConstructor()) {
047: isSpecialArgument = true; // constructor argument
048: } else {
049: AbstractMethodDeclaration methodDecl = scope
050: .referenceMethod();
051: if (methodDecl != null
052: && CharOperation.prefixEquals(SET,
053: methodDecl.selector)) {
054: isSpecialArgument = true; // setter argument
055: }
056: }
057: }
058: scope.problemReporter().localVariableHiding(this ,
059: existingVariable, isSpecialArgument);
060: }
061: }
062:
063: if (this .binding == null) {
064: this .binding = new LocalVariableBinding(this , typeBinding,
065: this .modifiers, true);
066: }
067: scope.addLocalVariable(this .binding);
068: resolveAnnotations(scope, this .annotations, this .binding);
069: //true stand for argument instead of just local
070: this .binding.declaration = this ;
071: this .binding.useFlag = used ? LocalVariableBinding.USED
072: : LocalVariableBinding.UNUSED;
073: }
074:
075: /**
076: * @see org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration#getKind()
077: */
078: public int getKind() {
079: return PARAMETER;
080: }
081:
082: public boolean isVarArgs() {
083: return this .type != null && (this .type.bits & IsVarArgs) != 0;
084: }
085:
086: public StringBuffer print(int indent, StringBuffer output) {
087:
088: printIndent(indent, output);
089: printModifiers(this .modifiers, output);
090: if (this .annotations != null)
091: printAnnotations(this .annotations, output);
092:
093: if (type == null) {
094: output.append("<no type> "); //$NON-NLS-1$
095: } else {
096: type.print(0, output).append(' ');
097: }
098: return output.append(this .name);
099: }
100:
101: public StringBuffer printStatement(int indent, StringBuffer output) {
102:
103: return print(indent, output).append(';');
104: }
105:
106: public TypeBinding resolveForCatch(BlockScope scope) {
107:
108: // resolution on an argument of a catch clause
109: // provide the scope with a side effect : insertion of a LOCAL
110: // that represents the argument. The type must be from JavaThrowable
111:
112: TypeBinding exceptionType = this .type
113: .resolveType(scope, true /* check bounds*/);
114: boolean hasError;
115: if (exceptionType == null) {
116: hasError = true;
117: } else {
118: hasError = false;
119: switch (exceptionType.kind()) {
120: case Binding.PARAMETERIZED_TYPE:
121: if (exceptionType.isBoundParameterizedType()) {
122: hasError = true;
123: scope.problemReporter()
124: .invalidParameterizedExceptionType(
125: exceptionType, this );
126: // fall thru to create the variable - avoids additional errors because the variable is missing
127: }
128: break;
129: case Binding.TYPE_PARAMETER:
130: scope.problemReporter().invalidTypeVariableAsException(
131: exceptionType, this );
132: hasError = true;
133: // fall thru to create the variable - avoids additional errors because the variable is missing
134: break;
135: case Binding.ARRAY_TYPE:
136: if (((ArrayBinding) exceptionType).leafComponentType == TypeBinding.VOID) {
137: scope.problemReporter()
138: .variableTypeCannotBeVoidArray(this );
139: hasError = true;
140: // fall thru to create the variable - avoids additional errors because the variable is missing
141: }
142: break;
143: }
144: if (exceptionType.findSuperTypeErasingTo(
145: TypeIds.T_JavaLangThrowable, true) == null) {
146: scope.problemReporter().cannotThrowType(this .type,
147: exceptionType);
148: hasError = true;
149: // fall thru to create the variable - avoids additional errors because the variable is missing
150: }
151: }
152: Binding existingVariable = scope
153: .getBinding(name, Binding.VARIABLE, this , false /*do not resolve hidden field*/);
154: if (existingVariable != null
155: && existingVariable.isValidBinding()) {
156: if (existingVariable instanceof LocalVariableBinding
157: && this .hiddenVariableDepth == 0) {
158: scope.problemReporter().redefineArgument(this );
159: } else {
160: scope.problemReporter().localVariableHiding(this ,
161: existingVariable, false);
162: }
163: }
164:
165: this .binding = new LocalVariableBinding(this , exceptionType,
166: modifiers, false); // argument decl, but local var (where isArgument = false)
167: resolveAnnotations(scope, this .annotations, this .binding);
168:
169: scope.addLocalVariable(binding);
170: binding.setConstant(Constant.NotAConstant);
171: if (hasError)
172: return null;
173: return exceptionType;
174: }
175:
176: public void traverse(ASTVisitor visitor, BlockScope scope) {
177:
178: if (visitor.visit(this , scope)) {
179: if (this .annotations != null) {
180: int annotationsLength = this .annotations.length;
181: for (int i = 0; i < annotationsLength; i++)
182: this .annotations[i].traverse(visitor, scope);
183: }
184: if (type != null)
185: type.traverse(visitor, scope);
186: }
187: visitor.endVisit(this , scope);
188: }
189:
190: public void traverse(ASTVisitor visitor, ClassScope scope) {
191:
192: if (visitor.visit(this , scope)) {
193: if (this .annotations != null) {
194: int annotationsLength = this .annotations.length;
195: for (int i = 0; i < annotationsLength; i++)
196: this.annotations[i].traverse(visitor, scope);
197: }
198: if (type != null)
199: type.traverse(visitor, scope);
200: }
201: visitor.endVisit(this, scope);
202: }
203: }
|