001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.codegen.*;
014: import org.eclipse.jdt.internal.compiler.flow.*;
015: import org.eclipse.jdt.internal.compiler.impl.Constant;
016: import org.eclipse.jdt.internal.compiler.lookup.*;
017:
018: public class QualifiedThisReference extends ThisReference {
019:
020: public TypeReference qualification;
021: ReferenceBinding currentCompatibleType;
022:
023: public QualifiedThisReference(TypeReference name, int sourceStart,
024: int sourceEnd) {
025: super (sourceStart, sourceEnd);
026: qualification = name;
027: name.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage
028: this .sourceStart = name.sourceStart;
029: }
030:
031: public FlowInfo analyseCode(BlockScope currentScope,
032: FlowContext flowContext, FlowInfo flowInfo) {
033:
034: return flowInfo;
035: }
036:
037: public FlowInfo analyseCode(BlockScope currentScope,
038: FlowContext flowContext, FlowInfo flowInfo,
039: boolean valueRequired) {
040:
041: return flowInfo;
042: }
043:
044: /**
045: * Code generation for QualifiedThisReference
046: *
047: * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
048: * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
049: * @param valueRequired boolean
050: */
051: public void generateCode(BlockScope currentScope,
052: CodeStream codeStream, boolean valueRequired) {
053:
054: int pc = codeStream.position;
055: if (valueRequired) {
056: if ((bits & DepthMASK) != 0) {
057: Object[] emulationPath = currentScope
058: .getEmulationPath(this .currentCompatibleType,
059: true /*only exact match*/, false/*consider enclosing arg*/);
060: codeStream.generateOuterAccess(emulationPath, this ,
061: this .currentCompatibleType, currentScope);
062: } else {
063: // nothing particular after all
064: codeStream.aload_0();
065: }
066: }
067: codeStream.recordPositionsFrom(pc, this .sourceStart);
068: }
069:
070: public TypeBinding resolveType(BlockScope scope) {
071:
072: constant = Constant.NotAConstant;
073: // X.this is not a param/raw type as denoting enclosing instance
074: TypeBinding type = this .qualification
075: .resolveType(scope, true /* check bounds*/);
076: if (type == null)
077: return null;
078: // X.this is not a param/raw type as denoting enclosing instance
079: type = type.erasure();
080:
081: // resolvedType needs to be converted to parameterized
082: if (type instanceof ReferenceBinding) {
083: this .resolvedType = scope
084: .environment()
085: .convertToParameterizedType((ReferenceBinding) type);
086: } else {
087: // error case
088: this .resolvedType = type;
089: }
090:
091: // the qualification MUST exactly match some enclosing type name
092: // It is possible to qualify 'this' by the name of the current class
093: int depth = 0;
094: this .currentCompatibleType = scope.referenceType().binding;
095: while (this .currentCompatibleType != null
096: && this .currentCompatibleType != type) {
097: depth++;
098: this .currentCompatibleType = this .currentCompatibleType
099: .isStatic() ? null : this .currentCompatibleType
100: .enclosingType();
101: }
102: bits &= ~DepthMASK; // flush previous depth if any
103: bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits
104:
105: if (this .currentCompatibleType == null) {
106: scope.problemReporter().noSuchEnclosingInstance(type, this ,
107: false);
108: return this .resolvedType;
109: }
110:
111: // Ensure one cannot write code like: B() { super(B.this); }
112: if (depth == 0) {
113: checkAccess(scope.methodScope());
114: } // if depth>0, path emulation will diagnose bad scenarii
115:
116: return this .resolvedType;
117: }
118:
119: public StringBuffer printExpression(int indent, StringBuffer output) {
120:
121: return qualification.print(0, output).append(".this"); //$NON-NLS-1$
122: }
123:
124: public void traverse(ASTVisitor visitor, BlockScope blockScope) {
125:
126: if (visitor.visit(this , blockScope)) {
127: qualification.traverse(visitor, blockScope);
128: }
129: visitor.endVisit(this , blockScope);
130: }
131:
132: public void traverse(ASTVisitor visitor, ClassScope blockScope) {
133:
134: if (visitor.visit(this, blockScope)) {
135: qualification.traverse(visitor, blockScope);
136: }
137: visitor.endVisit(this, blockScope);
138: }
139: }
|