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.internal.compiler.ASTVisitor;
013: import org.eclipse.jdt.internal.compiler.impl.Constant;
014: import org.eclipse.jdt.internal.compiler.lookup.*;
015:
016: public class JavadocFieldReference extends FieldReference {
017:
018: public int tagSourceStart, tagSourceEnd;
019: public int tagValue;
020: public MethodBinding methodBinding;
021:
022: public JavadocFieldReference(char[] source, long pos) {
023: super (source, pos);
024: this .bits |= InsideJavadoc;
025: }
026:
027: /*
028: public Binding getBinding() {
029: if (this.methodBinding != null) {
030: return this.methodBinding;
031: }
032: return this.binding;
033: }
034: */
035:
036: /*
037: * Resolves type on a Block or Class scope.
038: */
039: protected TypeBinding internalResolveType(Scope scope) {
040:
041: this .constant = Constant.NotAConstant;
042: if (this .receiver == null) {
043: this .receiverType = scope.enclosingSourceType();
044: } else if (scope.kind == Scope.CLASS_SCOPE) {
045: this .receiverType = this .receiver
046: .resolveType((ClassScope) scope);
047: } else {
048: this .receiverType = this .receiver
049: .resolveType((BlockScope) scope);
050: }
051: if (this .receiverType == null) {
052: return null;
053: }
054:
055: Binding fieldBinding = (this .receiver != null && this .receiver
056: .isThis()) ? scope
057: .classScope()
058: .getBinding(this .token,
059: this .bits & RestrictiveFlagMASK, this , true /*resolve*/)
060: : scope.getField(this .receiverType, this .token, this );
061: if (!fieldBinding.isValidBinding()) {
062: // implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient
063: switch (fieldBinding.problemId()) {
064: case ProblemReasons.NonStaticReferenceInConstructorInvocation:
065: case ProblemReasons.NonStaticReferenceInStaticContext:
066: case ProblemReasons.InheritedNameHidesEnclosingName:
067: FieldBinding closestMatch = ((ProblemFieldBinding) fieldBinding).closestMatch;
068: if (closestMatch != null) {
069: fieldBinding = closestMatch; // ignore problem if can reach target field through it
070: }
071: }
072: }
073: // When there's no valid field binding, try to resolve possible method reference without parenthesis
074: if (!fieldBinding.isValidBinding()
075: || !(fieldBinding instanceof FieldBinding)) {
076: if (this .receiverType instanceof ReferenceBinding) {
077: ReferenceBinding refBinding = (ReferenceBinding) this .receiverType;
078: MethodBinding[] methodBindings = refBinding
079: .getMethods(this .token);
080: if (methodBindings == null) {
081: scope.problemReporter().javadocInvalidField(
082: this .sourceStart, this .sourceEnd,
083: fieldBinding, this .receiverType,
084: scope.getDeclarationModifiers());
085: } else {
086: switch (methodBindings.length) {
087: case 0:
088: // no method was found: report problem
089: scope.problemReporter().javadocInvalidField(
090: this .sourceStart, this .sourceEnd,
091: fieldBinding, this .receiverType,
092: scope.getDeclarationModifiers());
093: break;
094: case 1:
095: // one method binding was found: store binding in specific field
096: this .methodBinding = methodBindings[0];
097: break;
098: default:
099: // several method binding were found: store first binding in specific field and report ambiguous error
100: this .methodBinding = methodBindings[0];
101: scope
102: .problemReporter()
103: .javadocAmbiguousMethodReference(
104: this .sourceStart,
105: this .sourceEnd, fieldBinding,
106: scope.getDeclarationModifiers());
107: break;
108: }
109: }
110: }
111: return null;
112: }
113: this .binding = (FieldBinding) fieldBinding;
114:
115: if (isFieldUseDeprecated(this .binding, scope,
116: (this .bits & IsStrictlyAssigned) != 0)) {
117: scope.problemReporter()
118: .javadocDeprecatedField(this .binding, this ,
119: scope.getDeclarationModifiers());
120: }
121: return this .resolvedType = this .binding.type;
122: }
123:
124: public boolean isSuperAccess() {
125: return (this .bits & ASTNode.SuperAccess) != 0;
126: }
127:
128: public StringBuffer printExpression(int indent, StringBuffer output) {
129:
130: if (this .receiver != null) {
131: this .receiver.printExpression(0, output);
132: }
133: output.append('#').append(this .token);
134: return output;
135: }
136:
137: public TypeBinding resolveType(BlockScope scope) {
138: return internalResolveType(scope);
139: }
140:
141: public TypeBinding resolveType(ClassScope scope) {
142: return internalResolveType(scope);
143: }
144:
145: /* (non-Javadoc)
146: * Redefine to capture javadoc specific signatures
147: * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
148: */
149: public void traverse(ASTVisitor visitor, BlockScope scope) {
150:
151: if (visitor.visit(this , scope)) {
152: if (this .receiver != null) {
153: this .receiver.traverse(visitor, scope);
154: }
155: }
156: visitor.endVisit(this , scope);
157: }
158:
159: public void traverse(ASTVisitor visitor, ClassScope scope) {
160:
161: if (visitor.visit(this, scope)) {
162: if (this.receiver != null) {
163: this.receiver.traverse(visitor, scope);
164: }
165: }
166: visitor.endVisit(this, scope);
167: }
168: }
|