added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / ClassLiteralAccess.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18
19 public class ClassLiteralAccess extends Expression {
20         
21         public TypeReference type;
22         public TypeBinding targetType;
23         FieldBinding syntheticField;
24
25         public ClassLiteralAccess(int sourceEnd, TypeReference t) {
26                 type = t;
27                 this.sourceStart = t.sourceStart;
28                 this.sourceEnd = sourceEnd;
29         }
30
31         public FlowInfo analyseCode(
32                 BlockScope currentScope,
33                 FlowContext flowContext,
34                 FlowInfo flowInfo) {
35
36                 // if reachable, request the addition of a synthetic field for caching the class descriptor
37                 SourceTypeBinding sourceType =
38                         currentScope.outerMostMethodScope().enclosingSourceType();
39                 if ((!(sourceType.isInterface()
40                                 // no field generated in interface case (would'nt verify) see 1FHHEZL
41                                 || sourceType.isBaseType()))
42                                 && currentScope.environment().options.sourceLevel <= ClassFileConstants.JDK1_5) {
43                         syntheticField = sourceType.addSyntheticFieldForClassLiteral(targetType, currentScope);
44                 }
45                 return flowInfo;
46         }
47
48         /**
49          * MessageSendDotClass code generation
50          *
51          * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
52          * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
53          * @param valueRequired boolean
54          */
55         public void generateCode(
56                 BlockScope currentScope,
57                 CodeStream codeStream,
58                 boolean valueRequired) {
59                 int pc = codeStream.position;
60
61                 // in interface case, no caching occurs, since cannot make a cache field for interface
62                 if (valueRequired) {
63                         codeStream.generateClassLiteralAccessForType(type.resolvedType, syntheticField);
64                         codeStream.generateImplicitConversion(this.implicitConversion);
65                 }
66                 codeStream.recordPositionsFrom(pc, this.sourceStart);
67         }
68
69         public StringBuffer printExpression(int indent, StringBuffer output) {
70
71                 return type.print(0, output).append(".class"); //$NON-NLS-1$
72         }
73
74         public TypeBinding resolveType(BlockScope scope) {
75
76                 constant = NotAConstant;
77                 if ((targetType = type.resolveType(scope, true /* check bounds*/)) == null)
78                         return null;
79
80                 if (targetType.isArrayType()
81                         && ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
82                         scope.problemReporter().cannotAllocateVoidArray(this);
83                         return null;
84                 } else if (targetType.isTypeVariable()) {
85                         scope.problemReporter().illegalClassLiteralForTypeVariable((TypeVariableBinding)targetType, this);
86                 }
87                 ReferenceBinding classType = scope.getJavaLangClass();
88                 if (classType.isGenericType()) {
89                     // Integer.class --> Class<Integer>, perform boxing of base types (int.class --> Class<Integer>)
90                     this.resolvedType = scope.createParameterizedType(classType, new TypeBinding[]{ scope.boxing(targetType) }, null/*not a member*/);
91                 } else {
92                     this.resolvedType = classType;
93                 }
94                 return this.resolvedType;
95         }
96
97         public void traverse(
98                 ASTVisitor visitor,
99                 BlockScope blockScope) {
100
101                 if (visitor.visit(this, blockScope)) {
102                         type.traverse(visitor, blockScope);
103                 }
104                 visitor.endVisit(this, blockScope);
105         }
106 }