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.classfmt.ClassFileConstants;
014: import org.eclipse.jdt.internal.compiler.codegen.*;
015: import org.eclipse.jdt.internal.compiler.flow.*;
016: import org.eclipse.jdt.internal.compiler.impl.Constant;
017: import org.eclipse.jdt.internal.compiler.lookup.*;
018:
019: public class ClassLiteralAccess extends Expression {
020:
021: public TypeReference type;
022: public TypeBinding targetType;
023: FieldBinding syntheticField;
024:
025: public ClassLiteralAccess(int sourceEnd, TypeReference type) {
026: this .type = type;
027: type.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage
028: this .sourceStart = type.sourceStart;
029: this .sourceEnd = sourceEnd;
030: }
031:
032: public FlowInfo analyseCode(BlockScope currentScope,
033: FlowContext flowContext, FlowInfo flowInfo) {
034:
035: // if reachable, request the addition of a synthetic field for caching the class descriptor
036: SourceTypeBinding sourceType = currentScope
037: .outerMostClassScope().enclosingSourceType();
038: // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=22334
039: if (!sourceType.isInterface()
040: && !sourceType.isBaseType()
041: && currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) {
042: syntheticField = sourceType
043: .addSyntheticFieldForClassLiteral(targetType,
044: currentScope);
045: }
046: return flowInfo;
047: }
048:
049: /**
050: * MessageSendDotClass code generation
051: *
052: * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
053: * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
054: * @param valueRequired boolean
055: */
056: public void generateCode(BlockScope currentScope,
057: CodeStream codeStream, boolean valueRequired) {
058: int pc = codeStream.position;
059:
060: // in interface case, no caching occurs, since cannot make a cache field for interface
061: if (valueRequired) {
062: codeStream.generateClassLiteralAccessForType(
063: type.resolvedType, syntheticField);
064: codeStream
065: .generateImplicitConversion(this .implicitConversion);
066: }
067: codeStream.recordPositionsFrom(pc, this .sourceStart);
068: }
069:
070: public StringBuffer printExpression(int indent, StringBuffer output) {
071:
072: return type.print(0, output).append(".class"); //$NON-NLS-1$
073: }
074:
075: public TypeBinding resolveType(BlockScope scope) {
076:
077: constant = Constant.NotAConstant;
078: if ((targetType = type
079: .resolveType(scope, true /* check bounds*/)) == null)
080: return null;
081:
082: if (targetType.isArrayType()) {
083: ArrayBinding arrayBinding = (ArrayBinding) this .targetType;
084: TypeBinding leafComponentType = arrayBinding.leafComponentType;
085: if (leafComponentType == TypeBinding.VOID) {
086: scope.problemReporter().cannotAllocateVoidArray(this );
087: return null;
088: } else if (leafComponentType.isTypeVariable()) {
089: scope
090: .problemReporter()
091: .illegalClassLiteralForTypeVariable(
092: (TypeVariableBinding) leafComponentType,
093: this );
094: }
095: } else if (this .targetType.isTypeVariable()) {
096: scope.problemReporter().illegalClassLiteralForTypeVariable(
097: (TypeVariableBinding) targetType, this );
098: }
099: ReferenceBinding classType = scope.getJavaLangClass();
100: if (classType.isGenericType()) {
101: // Integer.class --> Class<Integer>, perform boxing of base types (int.class --> Class<Integer>)
102: TypeBinding boxedType = null;
103: if (targetType.id == T_void) {
104: boxedType = scope.environment().getType(JAVA_LANG_VOID);
105: if (boxedType == null) {
106: boxedType = new ProblemReferenceBinding(
107: JAVA_LANG_VOID, null,
108: ProblemReasons.NotFound);
109: }
110: } else {
111: boxedType = scope.boxing(targetType);
112: }
113: this .resolvedType = scope
114: .environment()
115: .createParameterizedType(classType,
116: new TypeBinding[] { boxedType }, null/*not a member*/);
117: } else {
118: this .resolvedType = classType;
119: }
120: return this .resolvedType;
121: }
122:
123: public void traverse(ASTVisitor visitor, BlockScope blockScope) {
124:
125: if (visitor.visit(this, blockScope)) {
126: type.traverse(visitor, blockScope);
127: }
128: visitor.endVisit(this, blockScope);
129: }
130: }
|