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.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
23 public class QualifiedThisReference extends ThisReference {
25 public TypeReference qualification;
26 ReferenceBinding currentCompatibleType;
28 public QualifiedThisReference(TypeReference name, int pos, int sourceEnd) {
31 this.sourceEnd = sourceEnd;
32 this.sourceStart = name.sourceStart;
35 public FlowInfo analyseCode(
36 BlockScope currentScope,
37 FlowContext flowContext,
40 manageEnclosingInstanceAccessIfNecessary(currentScope);
44 public FlowInfo analyseCode(
45 BlockScope currentScope,
46 FlowContext flowContext,
48 boolean valueRequired) {
51 manageEnclosingInstanceAccessIfNecessary(currentScope);
56 protected boolean checkAccess(
57 MethodScope methodScope,
58 TypeBinding targetType) {
60 // this/super cannot be used in constructor call
61 if (methodScope.isConstructorCall) {
62 methodScope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this);
66 // static may not refer to this/super
67 if (methodScope.isStatic) {
68 methodScope.problemReporter().incorrectEnclosingInstanceReference(
77 * Code generation for QualifiedThisReference
79 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
80 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
81 * @param valueRequired boolean
83 public void generateCode(
84 BlockScope currentScope,
85 CodeStream codeStream,
86 boolean valueRequired) {
88 int pc = codeStream.position;
90 if ((bits & DepthMASK) != 0) {
91 Object[] emulationPath =
92 currentScope.getExactEmulationPath(currentCompatibleType);
93 if (emulationPath == null) {
94 // internal error, per construction we should have found it
95 currentScope.problemReporter().needImplementation();
97 codeStream.generateOuterAccess(emulationPath, this, currentScope);
100 // nothing particular after all
101 codeStream.aload_0();
104 codeStream.recordPositionsFrom(pc, this.sourceStart);
107 void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
109 currentScope.emulateOuterAccess(
110 (SourceTypeBinding) currentCompatibleType,
112 // request cascade of accesses
115 public TypeBinding resolveType(BlockScope scope) {
117 constant = NotAConstant;
118 TypeBinding qualificationTb = qualification.resolveType(scope);
119 if (qualificationTb == null)
122 // the qualification MUST exactly match some enclosing type name
123 // Its possible to qualify 'this' by the name of the current class
125 currentCompatibleType = scope.referenceType().binding;
126 while (currentCompatibleType != null
127 && currentCompatibleType != qualificationTb) {
129 currentCompatibleType =
130 currentCompatibleType.isStatic() ? null : currentCompatibleType.enclosingType();
132 bits &= ~DepthMASK; // flush previous depth if any
133 bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits
135 if (currentCompatibleType == null) {
136 scope.problemReporter().incorrectEnclosingInstanceReference(
142 // Ensure one cannot write code like: B() { super(B.this); }
144 if (!checkAccess(scope.methodScope(), qualificationTb))
147 // Could also be targeting an enclosing instance inside a super constructor invocation
150 // this(new Object() { Object obj = X.this; });
154 MethodScope methodScope = scope.methodScope();
155 while (methodScope != null) {
156 if (methodScope.enclosingSourceType() == currentCompatibleType) {
157 if (!this.checkAccess(methodScope, qualificationTb))
161 methodScope = methodScope.parent.methodScope();
164 return qualificationTb;
167 public String toStringExpression() {
169 return qualification.toString(0) + ".this"; //$NON-NLS-1$
172 public void traverse(
173 IAbstractSyntaxTreeVisitor visitor,
174 BlockScope blockScope) {
176 if (visitor.visit(this, blockScope)) {
177 qualification.traverse(visitor, blockScope);
179 visitor.endVisit(this, blockScope);