1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.*;
15 import net.sourceforge.phpdt.internal.compiler.flow.*;
16 import net.sourceforge.phpdt.internal.compiler.lookup.*;
18 public class QualifiedThisReference extends ThisReference {
20 public TypeReference qualification;
21 ReferenceBinding currentCompatibleType;
23 public QualifiedThisReference(TypeReference name, int pos, int sourceEnd) {
26 this.sourceEnd = sourceEnd;
27 this.sourceStart = name.sourceStart;
30 public FlowInfo analyseCode(
31 BlockScope currentScope,
32 FlowContext flowContext,
35 manageEnclosingInstanceAccessIfNecessary(currentScope);
39 public FlowInfo analyseCode(
40 BlockScope currentScope,
41 FlowContext flowContext,
43 boolean valueRequired) {
46 manageEnclosingInstanceAccessIfNecessary(currentScope);
51 protected boolean checkAccess(
52 MethodScope methodScope,
53 TypeBinding targetType) {
55 // this/super cannot be used in constructor call
56 if (methodScope.isConstructorCall) {
57 methodScope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this);
61 // static may not refer to this/super
62 if (methodScope.isStatic) {
63 methodScope.problemReporter().incorrectEnclosingInstanceReference(
72 * Code generation for QualifiedThisReference
74 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
75 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
76 * @param valueRequired boolean
78 public void generateCode(
79 BlockScope currentScope,
80 CodeStream codeStream,
81 boolean valueRequired) {
83 int pc = codeStream.position;
85 if ((bits & DepthMASK) != 0) {
86 Object[] emulationPath =
87 currentScope.getExactEmulationPath(currentCompatibleType);
88 if (emulationPath == null) {
89 // internal error, per construction we should have found it
90 currentScope.problemReporter().needImplementation();
92 codeStream.generateOuterAccess(emulationPath, this, currentScope);
95 // nothing particular after all
99 codeStream.recordPositionsFrom(pc, this.sourceStart);
102 void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
104 currentScope.emulateOuterAccess(
105 (SourceTypeBinding) currentCompatibleType,
107 // request cascade of accesses
110 public TypeBinding resolveType(BlockScope scope) {
112 constant = NotAConstant;
113 TypeBinding qualificationTb = qualification.resolveType(scope);
114 if (qualificationTb == null)
117 // the qualification MUST exactly match some enclosing type name
118 // Its possible to qualify 'this' by the name of the current class
120 currentCompatibleType = scope.referenceType().binding;
121 while (currentCompatibleType != null
122 && currentCompatibleType != qualificationTb) {
124 currentCompatibleType =
125 currentCompatibleType.isStatic() ? null : currentCompatibleType.enclosingType();
127 bits &= ~DepthMASK; // flush previous depth if any
128 bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits
130 if (currentCompatibleType == null) {
131 scope.problemReporter().incorrectEnclosingInstanceReference(
137 // Ensure one cannot write code like: B() { super(B.this); }
139 if (!checkAccess(scope.methodScope(), qualificationTb))
142 // Could also be targeting an enclosing instance inside a super constructor invocation
145 // this(new Object() { Object obj = X.this; });
149 MethodScope methodScope = scope.methodScope();
150 while (methodScope != null) {
151 if (methodScope.enclosingSourceType() == currentCompatibleType) {
152 if (!this.checkAccess(methodScope, qualificationTb))
156 methodScope = methodScope.parent.methodScope();
159 return qualificationTb;
162 public String toStringExpression() {
164 return qualification.toString(0) + ".this"; //$NON-NLS-1$
167 public void traverse(
168 IAbstractSyntaxTreeVisitor visitor,
169 BlockScope blockScope) {
171 if (visitor.visit(this, blockScope)) {
172 qualification.traverse(visitor, blockScope);
174 visitor.endVisit(this, blockScope);