1 /******************************************************************************* 2 * Copyright (c) 2000, 2004 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.internal.compiler.ast; 12 13 import org.eclipse.jdt.core.compiler.CharOperation; 14 import org.eclipse.jdt.internal.compiler.ASTVisitor; 15 import org.eclipse.jdt.internal.compiler.lookup.*; 16 17 public class Argument extends LocalDeclaration { 18 19 // prefix for setter method (to recognize special hiding argument) 20 private final static char[] SET = "set".toCharArray(); //$NON-NLS-1$ 21 public boolean isVarArgs; 22 Argument(char[] name, long posNom, TypeReference tr, int modifiers, boolean isVarArgs)23 public Argument(char[] name, long posNom, TypeReference tr, int modifiers, boolean isVarArgs) { 24 25 super(name, (int) (posNom >>> 32), (int) posNom); 26 this.declarationSourceEnd = (int) posNom; 27 this.modifiers = modifiers; 28 type = tr; 29 this.bits |= IsLocalDeclarationReachableMASK; 30 this.isVarArgs = isVarArgs; 31 } 32 bind(MethodScope scope, TypeBinding typeBinding, boolean used)33 public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) { 34 35 if (this.type != null) 36 this.type.resolvedType = typeBinding; // TODO (philippe) no longer necessary as when binding got resolved, it was recorded already (SourceTypeBinding#resolveTypesFor(MethodBinding)) 37 // record the resolved type into the type reference 38 int modifierFlag = this.modifiers; 39 40 Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/); 41 if (existingVariable != null && existingVariable.isValidBinding()){ 42 if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) { 43 scope.problemReporter().redefineArgument(this); 44 return; 45 } 46 boolean isSpecialArgument = false; 47 if (existingVariable instanceof FieldBinding) { 48 if (scope.isInsideConstructor()) { 49 isSpecialArgument = true; // constructor argument 50 } else { 51 AbstractMethodDeclaration methodDecl = scope.referenceMethod(); 52 if (methodDecl != null && CharOperation.prefixEquals(SET, methodDecl.selector)) { 53 isSpecialArgument = true; // setter argument 54 } 55 } 56 } 57 scope.problemReporter().localVariableHiding(this, existingVariable, isSpecialArgument); 58 } 59 60 scope.addLocalVariable( 61 this.binding = 62 new LocalVariableBinding(this, typeBinding, modifierFlag, true)); 63 //true stand for argument instead of just local 64 this.binding.declaration = this; 65 this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED; 66 } 67 print(int indent, StringBuffer output)68 public StringBuffer print(int indent, StringBuffer output) { 69 70 printIndent(indent, output); 71 printModifiers(this.modifiers, output); 72 if (type == null) { 73 output.append("<no type> "); //$NON-NLS-1$ 74 } else { 75 type.print(0, output).append(' '); 76 } 77 return output.append(this.name); 78 } 79 printStatement(int indent, StringBuffer output)80 public StringBuffer printStatement(int indent, StringBuffer output) { 81 82 return print(indent, output).append(';'); 83 } 84 resolveForCatch(BlockScope scope)85 public TypeBinding resolveForCatch(BlockScope scope) { 86 87 // resolution on an argument of a catch clause 88 // provide the scope with a side effect : insertion of a LOCAL 89 // that represents the argument. The type must be from JavaThrowable 90 91 TypeBinding exceptionType = this.type.resolveType(scope); 92 if (exceptionType == null) return null; 93 if (exceptionType.isGenericType() || exceptionType.isParameterizedType()) { 94 scope.problemReporter().invalidParameterizedExceptionType(exceptionType, this); 95 return null; 96 } 97 if (exceptionType.isTypeVariable()) { 98 scope.problemReporter().invalidTypeVariableAsException(exceptionType, this); 99 return null; 100 } 101 TypeBinding throwable = scope.getJavaLangThrowable(); 102 if (!exceptionType.isCompatibleWith(throwable)) { 103 scope.problemReporter().typeMismatchError(exceptionType, throwable, this); 104 return null; 105 } 106 107 Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/); 108 if (existingVariable != null && existingVariable.isValidBinding()){ 109 if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) { 110 scope.problemReporter().redefineArgument(this); 111 return null; 112 } 113 scope.problemReporter().localVariableHiding(this, existingVariable, false); 114 } 115 116 binding = new LocalVariableBinding(this, exceptionType, modifiers, false); // argument decl, but local var (where isArgument = false) 117 scope.addLocalVariable(binding); 118 binding.setConstant(NotAConstant); 119 return exceptionType; 120 } 121 traverse(ASTVisitor visitor, BlockScope scope)122 public void traverse(ASTVisitor visitor, BlockScope scope) { 123 124 if (visitor.visit(this, scope)) { 125 if (type != null) 126 type.traverse(visitor, scope); 127 if (initialization != null) 128 initialization.traverse(visitor, scope); 129 } 130 visitor.endVisit(this, scope); 131 } 132 } 133