History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/javac/SourceMember.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/javac/SourceMember.java+907−0
@@ -0,0 +1,907 @@
1+/*
2+ * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.javac;
27+
28+import sun.tools.java.*;
29+import sun.tools.tree.*;
30+import sun.tools.asm.*;
31+import java.util.Vector;
32+import java.util.Enumeration;
33+import java.util.Hashtable;
34+import java.io.PrintStream;
35+
36+/**
37+ * A Source Member
38+ *
39+ * WARNING: The contents of this source file are not part of any
40+ * supported API. Code that depends on them does so at its own risk:
41+ * they are subject to change or removal without notice.
42+ */
43+@Deprecated
44+public
45+class SourceMember extends MemberDefinition implements Constants {
46+ /**
47+ * The argument names (if it is a method)
48+ */
49+ Vector args;
50+
51+ // set to the MemberDefinition in the interface if we have this field because
52+ // it has been forced on us
53+ MemberDefinition abstractSource;
54+
55+ /**
56+ * The status of the field
57+ */
58+ int status;
59+
60+ static final int PARSED = 0;
61+ static final int CHECKING = 1;
62+ static final int CHECKED = 2;
63+ static final int INLINING = 3;
64+ static final int INLINED = 4;
65+ static final int ERROR = 5;
66+
67+ public Vector getArguments() {
68+ return args;
69+ }
70+
71+ /**
72+ * Constructor
73+ * @param argNames a vector of IdentifierToken
74+ */
75+ public SourceMember(long where, ClassDefinition clazz,
76+ String doc, int modifiers, Type type,
77+ Identifier name, Vector argNames,
78+ IdentifierToken exp[], Node value) {
79+ super(where, clazz, modifiers, type, name, exp, value);
80+ this.documentation = doc;
81+ this.args = argNames; // for the moment
82+ // not until type names are resolved: createArgumentFields(argNames);
83+
84+ if (ClassDefinition.containsDeprecated(documentation)) {
85+ this.modifiers |= M_DEPRECATED;
86+ }
87+ }
88+
89+ void createArgumentFields(Vector argNames) {
90+ // Create a list of arguments
91+ if (isMethod()) {
92+ args = new Vector();
93+
94+ if (isConstructor() || !(isStatic() || isInitializer())) {
95+ args.addElement(((SourceClass)clazz).getThisArgument());
96+ }
97+
98+ if (argNames != null) {
99+ Enumeration e = argNames.elements();
100+ Type argTypes[] = getType().getArgumentTypes();
101+ for (int i = 0 ; i < argTypes.length ; i++) {
102+ Object x = e.nextElement();
103+ if (x instanceof LocalMember) {
104+ // This should not happen, but it does
105+ // in cases of vicious cyclic inheritance.
106+ args = argNames;
107+ return;
108+ }
109+ Identifier id;
110+ int mod;
111+ long where;
112+ if (x instanceof Identifier) {
113+ // allow argNames to be simple Identifiers (deprecated!)
114+ id = (Identifier)x;
115+ mod = 0;
116+ where = getWhere();
117+ } else {
118+ IdentifierToken token = (IdentifierToken)x;
119+ id = token.getName();
120+ mod = token.getModifiers();
121+ where = token.getWhere();
122+ }
123+ args.addElement(new LocalMember(where, clazz, mod,
124+ argTypes[i], id));
125+ }
126+ }
127+ }
128+ }
129+
130+ // The methods addOuterThis() and addUplevelArguments() were
131+ // both originally part of a single method called addUplevelArguments()
132+ // which took a single boolean parameter describing which of the
133+ // two behaviors it wanted.
134+ //
135+ // The original addUplevelArguments() claimed to keep the arguments in
136+ // the following order:
137+ //
138+ // (1) <this> <early outer this> <uplevel arguments...> <true arguments...>
139+ //
140+ // (By <early outer this> I am referring to the clientOuterField added
141+ // to some constructors when they are created. If an outer this is
142+ // added later, on demand, then this is mixed in with the rest of the
143+ // uplevel arguments and is added by addUplevelArguments.)
144+ //
145+ // In reality, the `args' Vector was generated in this order, but the
146+ // Type array `argTypes' was generated as:
147+ //
148+ // (2) <this> <uplevel arguments...> <early outer this> <true arguments...>
149+ //
150+ // This didn't make a difference in the common case -- that is, when
151+ // a class had an <outer.this> or <uplevel arguments...> but not both.
152+ // Both can happen in the case that a member class is declared inside
153+ // of a local class. It seems that the calling sequences, generated
154+ // in places like NewInstanceExpression.codeCommon(), use order (2),
155+ // so I have changed the code below to stick with that order. Since
156+ // the only time this happens is in classes which are insideLocal, no
157+ // one should be able to tell the difference between these orders.
158+ // (bug number 4085633)
159+
160+ LocalMember outerThisArg = null;
161+
162+ /**
163+ * Get outer instance link, or null if none.
164+ */
165+
166+ public LocalMember getOuterThisArg() {
167+ return outerThisArg;
168+ }
169+
170+ /**
171+ * Add the outer.this argument to the list of arguments for this
172+ * constructor. This is called from resolveTypeStructure. Any
173+ * additional uplevel arguments get added later by addUplevelArguments().
174+ */
175+
176+ void addOuterThis() {
177+ UplevelReference refs = clazz.getReferences();
178+
179+ // See if we have a client outer field.
180+ while (refs != null &&
181+ !refs.isClientOuterField()) {
182+ refs = refs.getNext();
183+ }
184+
185+ // There is no outer this argument. Quit.
186+ if (refs == null) {
187+ return;
188+ }
189+
190+ // Get the old arg types.
191+ Type oldArgTypes[] = type.getArgumentTypes();
192+
193+ // And make an array for the new ones with space for one more.
194+ Type argTypes[] = new Type[oldArgTypes.length + 1];
195+
196+ LocalMember arg = refs.getLocalArgument();
197+ outerThisArg = arg;
198+
199+ // args is our list of arguments. It contains a `this', so
200+ // we insert at position 1. The list of types does not have a
201+ // this, so we insert at position 0.
202+ args.insertElementAt(arg, 1);
203+ argTypes[0] = arg.getType();
204+
205+ // Add on the rest of the constructor arguments.
206+ for (int i = 0; i < oldArgTypes.length; i++) {
207+ argTypes[i + 1] = oldArgTypes[i];
208+ }
209+
210+ type = Type.tMethod(type.getReturnType(), argTypes);
211+ }
212+
213+ /**
214+ * Prepend argument names and argument types for local variable references.
215+ * This information is never seen by the type-check phase,
216+ * but it affects code generation, which is the earliest moment
217+ * we have comprehensive information on uplevel references.
218+ * The code() methods tweaks the constructor calls, prepending
219+ * the proper values to the argument list.
220+ */
221+ void addUplevelArguments() {
222+ UplevelReference refs = clazz.getReferences();
223+ clazz.getReferencesFrozen();
224+
225+ // Count how many uplevels we have to add.
226+ int count = 0;
227+ for (UplevelReference r = refs; r != null; r = r.getNext()) {
228+ if (!r.isClientOuterField()) {
229+ count += 1;
230+ }
231+ }
232+
233+ if (count == 0) {
234+ // None to add, quit.
235+ return;
236+ }
237+
238+ // Get the old argument types.
239+ Type oldArgTypes[] = type.getArgumentTypes();
240+
241+ // Make an array with enough room for the new.
242+ Type argTypes[] = new Type[oldArgTypes.length + count];
243+
244+ // Add all of the late uplevel references to args and argTypes.
245+ // Note that they are `off-by-one' because of the `this'.
246+ int ins = 0;
247+ for (UplevelReference r = refs; r != null; r = r.getNext()) {
248+ if (!r.isClientOuterField()) {
249+ LocalMember arg = r.getLocalArgument();
250+
251+ args.insertElementAt(arg, 1 + ins);
252+ argTypes[ins] = arg.getType();
253+
254+ ins++;
255+ }
256+ }
257+
258+ // Add the rest of the old arguments.
259+ for (int i = 0; i < oldArgTypes.length; i++) {
260+ argTypes[ins + i] = oldArgTypes[i];
261+ }
262+
263+ type = Type.tMethod(type.getReturnType(), argTypes);
264+ }
265+
266+ /**
267+ * Constructor for an inner class.
268+ */
269+ public SourceMember(ClassDefinition innerClass) {
270+ super(innerClass);
271+ }
272+
273+ /**
274+ * Constructor.
275+ * Used only to generate an abstract copy of a method that a class
276+ * inherits from an interface
277+ */
278+ public SourceMember(MemberDefinition f, ClassDefinition c, Environment env) {
279+ this(f.getWhere(), c, f.getDocumentation(),
280+ f.getModifiers() | M_ABSTRACT, f.getType(), f.getName(), null,
281+ f.getExceptionIds(), null);
282+ this.args = f.getArguments();
283+ this.abstractSource = f;
284+ this.exp = f.getExceptions(env);
285+ }
286+
287+ /**
288+ * Get exceptions
289+ */
290+ public ClassDeclaration[] getExceptions(Environment env) {
291+ if ((!isMethod()) || (exp != null)) {
292+ return exp;
293+ }
294+ if (expIds == null) {
295+ // (should not happen)
296+ exp = new ClassDeclaration[0];
297+ return exp;
298+ }
299+ // be sure to get the imports right:
300+ env = ((SourceClass)getClassDefinition()).setupEnv(env);
301+ exp = new ClassDeclaration[expIds.length];
302+ for (int i = 0; i < exp.length; i++) {
303+ Identifier e = expIds[i].getName();
304+ Identifier rexp = getClassDefinition().resolveName(env, e);
305+ exp[i] = env.getClassDeclaration(rexp);
306+ }
307+ return exp;
308+ }
309+
310+ /**
311+ * Set array of name-resolved exceptions directly, e.g., for access methods.
312+ */
313+ public void setExceptions(ClassDeclaration[] exp) {
314+ this.exp = exp;
315+ }
316+
317+ /**
318+ * Resolve types in a field, after parsing.
319+ * @see ClassDefinition.resolveTypeStructure
320+ */
321+
322+ public boolean resolved = false;
323+
324+ public void resolveTypeStructure(Environment env) {
325+ if (tracing) env.dtEnter("SourceMember.resolveTypeStructure: " + this);
326+
327+ // A member should only be resolved once. For a constructor, it is imperative
328+ // that 'addOuterThis' be called only once, else the outer instance argument may
329+ // be inserted into the argument list multiple times.
330+
331+ if (resolved) {
332+ if (tracing) env.dtEvent("SourceMember.resolveTypeStructure: OK " + this);
333+ // This case shouldn't be happening. It is the responsibility
334+ // of our callers to avoid attempting multiple resolutions of a member.
335+ // *** REMOVE FOR SHIPMENT? ***
336+ throw new CompilerError("multiple member type resolution");
337+ //return;
338+ } else {
339+ if (tracing) env.dtEvent("SourceMember.resolveTypeStructure: RESOLVING " + this);
340+ resolved = true;
341+ }
342+
343+ super.resolveTypeStructure(env);
344+ if (isInnerClass()) {
345+ ClassDefinition nc = getInnerClass();
346+ if (nc instanceof SourceClass && !nc.isLocal()) {
347+ ((SourceClass)nc).resolveTypeStructure(env);
348+ }
349+ type = innerClass.getType();
350+ } else {
351+ // Expand all class names in 'type', including those that are not
352+ // fully-qualified or refer to inner classes, into fully-qualified
353+ // names. Local and anonymous classes get synthesized names here,
354+ // corresponding to the class files that will be generated. This is
355+ // currently the only place where 'resolveNames' is used.
356+ type = env.resolveNames(getClassDefinition(), type, isSynthetic());
357+
358+ // do the throws also:
359+ getExceptions(env);
360+
361+ if (isMethod()) {
362+ Vector argNames = args; args = null;
363+ createArgumentFields(argNames);
364+ // Add outer instance argument for constructors.
365+ if (isConstructor()) {
366+ addOuterThis();
367+ }
368+ }
369+ }
370+ if (tracing) env.dtExit("SourceMember.resolveTypeStructure: " + this);
371+ }
372+
373+ /**
374+ * Get the class declaration in which the field is actually defined
375+ */
376+ public ClassDeclaration getDefiningClassDeclaration() {
377+ if (abstractSource == null)
378+ return super.getDefiningClassDeclaration();
379+ else
380+ return abstractSource.getDefiningClassDeclaration();
381+ }
382+
383+ /**
384+ * A source field never reports deprecation, since the compiler
385+ * allows access to deprecated features that are being compiled
386+ * in the same job.
387+ */
388+ public boolean reportDeprecated(Environment env) {
389+ return false;
390+ }
391+
392+ /**
393+ * Check this field.
394+ * <p>
395+ * This is the method which requests checking.
396+ * The real work is done by
397+ * <tt>Vset check(Environment, Context, Vset)</tt>.
398+ */
399+ public void check(Environment env) throws ClassNotFound {
400+ if (tracing) env.dtEnter("SourceMember.check: " +
401+ getName() + ", status = " + status);
402+ // rely on the class to check all fields in the proper order
403+ if (status == PARSED) {
404+ if (isSynthetic() && getValue() == null) {
405+ // break a big cycle for small synthetic variables
406+ status = CHECKED;
407+ if (tracing)
408+ env.dtExit("SourceMember.check: BREAKING CYCLE");
409+ return;
410+ }
411+ if (tracing) env.dtEvent("SourceMember.check: CHECKING CLASS");
412+ clazz.check(env);
413+ if (status == PARSED) {
414+ if (getClassDefinition().getError()) {
415+ status = ERROR;
416+ } else {
417+ if (tracing)
418+ env.dtExit("SourceMember.check: CHECK FAILED");
419+ throw new CompilerError("check failed");
420+ }
421+ }
422+ }
423+ if (tracing) env.dtExit("SourceMember.check: DONE " +
424+ getName() + ", status = " + status);
425+ }
426+
427+ /**
428+ * Check a field.
429+ * @param vset tells which uplevel variables are definitely assigned
430+ * The vset is also used to track the initialization of blank finals
431+ * by whichever fields which are relevant to them.
432+ */
433+ public Vset check(Environment env, Context ctx, Vset vset) throws ClassNotFound {
434+ if (tracing) env.dtEvent("SourceMember.check: MEMBER " +
435+ getName() + ", status = " + status);
436+ if (status == PARSED) {
437+ if (isInnerClass()) {
438+ // some classes are checked separately
439+ ClassDefinition nc = getInnerClass();
440+ if (nc instanceof SourceClass && !nc.isLocal()
441+ && nc.isInsideLocal()) {
442+ status = CHECKING;
443+ vset = ((SourceClass)nc).checkInsideClass(env, ctx, vset);
444+ }
445+ status = CHECKED;
446+ return vset;
447+ }
448+ if (env.dump()) {
449+ System.out.println("[check field " + getClassDeclaration().getName() + "." + getName() + "]");
450+ if (getValue() != null) {
451+ getValue().print(System.out);
452+ System.out.println();
453+ }
454+ }
455+ env = new Environment(env, this);
456+
457+ // This is where all checking of names appearing within the type
458+ // of the member is done. Includes return type and argument types.
459+ // Since only one location ('where') for error messages is provided,
460+ // localization of errors is poor. Throws clauses are handled below.
461+ env.resolve(where, getClassDefinition(), getType());
462+
463+ // Make sure that all the classes that we claim to throw really
464+ // are subclasses of Throwable, and are classes that we can reach
465+ if (isMethod()) {
466+ ClassDeclaration throwable =
467+ env.getClassDeclaration(idJavaLangThrowable);
468+ ClassDeclaration exp[] = getExceptions(env);
469+ for (int i = 0 ; i < exp.length ; i++) {
470+ ClassDefinition def;
471+ long where = getWhere();
472+ if (expIds != null && i < expIds.length) {
473+ where = IdentifierToken.getWhere(expIds[i], where);
474+ }
475+ try {
476+ def = exp[i].getClassDefinition(env);
477+
478+ // Validate access for all inner-class components
479+ // of a qualified name, not just the last one, which
480+ // is checked below. Yes, this is a dirty hack...
481+ // Part of fix for 4094658.
482+ env.resolveByName(where, getClassDefinition(), def.getName());
483+
484+ } catch (ClassNotFound e) {
485+ env.error(where, "class.not.found", e.name, "throws");
486+ break;
487+ }
488+ def.noteUsedBy(getClassDefinition(), where, env);
489+ if (!getClassDefinition().
490+ canAccess(env, def.getClassDeclaration())) {
491+ env.error(where, "cant.access.class", def);
492+ } else if (!def.subClassOf(env, throwable)) {
493+ env.error(where, "throws.not.throwable", def);
494+ }
495+ }
496+ }
497+
498+ status = CHECKING;
499+
500+ if (isMethod() && args != null) {
501+ int length = args.size();
502+ outer_loop:
503+ for (int i = 0; i < length; i++) {
504+ LocalMember lf = (LocalMember)(args.elementAt(i));
505+ Identifier name_i = lf.getName();
506+ for (int j = i + 1; j < length; j++) {
507+ LocalMember lf2 = (LocalMember)(args.elementAt(j));
508+ Identifier name_j = lf2.getName();
509+ if (name_i.equals(name_j)) {
510+ env.error(lf2.getWhere(), "duplicate.argument",
511+ name_i);
512+ break outer_loop;
513+ }
514+ }
515+ }
516+ }
517+
518+ if (getValue() != null) {
519+ ctx = new Context(ctx, this);
520+
521+ if (isMethod()) {
522+ Statement s = (Statement)getValue();
523+ // initialize vset, indication that each of the arguments
524+ // to the function has a value
525+
526+ for (Enumeration e = args.elements(); e.hasMoreElements();){
527+ LocalMember f = (LocalMember)e.nextElement();
528+ vset.addVar(ctx.declare(env, f));
529+ }
530+
531+ if (isConstructor()) {
532+ // Undefine "this" in some constructors, until after
533+ // the super constructor has been called.
534+ vset.clearVar(ctx.getThisNumber());
535+
536+ // If the first thing in the definition isn't a call
537+ // to either super() or this(), then insert one.
538+ Expression supCall = s.firstConstructor();
539+ if ((supCall == null)
540+ && (getClassDefinition().getSuperClass() != null)) {
541+ supCall = getDefaultSuperCall(env);
542+ Statement scs = new ExpressionStatement(where,
543+ supCall);
544+ s = Statement.insertStatement(scs, s);
545+ setValue(s);
546+ }
547+ }
548+
549+ //System.out.println("VSET = " + vset);
550+ ClassDeclaration exp[] = getExceptions(env);
551+ int htsize = (exp.length > 3) ? 17 : 7;
552+ Hashtable thrown = new Hashtable(htsize);
553+
554+ vset = s.checkMethod(env, ctx, vset, thrown);
555+
556+ ClassDeclaration ignore1 =
557+ env.getClassDeclaration(idJavaLangError);
558+ ClassDeclaration ignore2 =
559+ env.getClassDeclaration(idJavaLangRuntimeException);
560+
561+ for (Enumeration e = thrown.keys(); e.hasMoreElements();) {
562+ ClassDeclaration c = (ClassDeclaration)e.nextElement();
563+ ClassDefinition def = c.getClassDefinition(env);
564+ if (def.subClassOf(env, ignore1)
565+ || def.subClassOf(env, ignore2)) {
566+ continue;
567+ }
568+
569+ boolean ok = false;
570+ if (!isInitializer()) {
571+ for (int i = 0 ; i < exp.length ; i++) {
572+ if (def.subClassOf(env, exp[i])) {
573+ ok = true;
574+ }
575+ }
576+ }
577+ if (!ok) {
578+ Node n = (Node)thrown.get(c);
579+ long where = n.getWhere();
580+ String errorMsg;
581+
582+ if (isConstructor()) {
583+ if (where ==
584+ getClassDefinition().getWhere()) {
585+
586+ // If this message is being generated for
587+ // a default constructor, we should give
588+ // a different error message. Currently
589+ // we check for this by seeing if the
590+ // constructor has the same "where" as
591+ // its class. This is a bit kludgy, but
592+ // works. (bug id 4034836)
593+ errorMsg = "def.constructor.exception";
594+ } else {
595+ // Constructor with uncaught exception.
596+ errorMsg = "constructor.exception";
597+ }
598+ } else if (isInitializer()) {
599+ // Initializer with uncaught exception.
600+ errorMsg = "initializer.exception";
601+ } else {
602+ // Method with uncaught exception.
603+ errorMsg = "uncaught.exception";
604+ }
605+ env.error(where, errorMsg, c.getName());
606+ }
607+ }
608+ } else {
609+ Hashtable thrown = new Hashtable(3); // small & throw-away
610+ Expression val = (Expression)getValue();
611+
612+ vset = val.checkInitializer(env, ctx, vset,
613+ getType(), thrown);
614+ setValue(val.convert(env, ctx, getType(), val));
615+
616+ // Complain about static final members of inner classes that
617+ // do not have an initializer that is a constant expression.
618+ // In general, static members are not permitted for inner
619+ // classes, but an exception is made for named constants.
620+ // Other cases of static members, including non-final ones,
621+ // are handled in 'SourceClass'. Part of fix for 4095568.
622+ if (isStatic() && isFinal() && !clazz.isTopLevel()) {
623+ if (!((Expression)getValue()).isConstant()) {
624+ env.error(where, "static.inner.field", getName(), this);
625+ setValue(null);
626+ }
627+ }
628+
629+
630+ // Both RuntimeExceptions and Errors should be
631+ // allowed in initializers. Fix for bug 4102541.
632+ ClassDeclaration except =
633+ env.getClassDeclaration(idJavaLangThrowable);
634+ ClassDeclaration ignore1 =
635+ env.getClassDeclaration(idJavaLangError);
636+ ClassDeclaration ignore2 =
637+ env.getClassDeclaration(idJavaLangRuntimeException);
638+
639+ for (Enumeration e = thrown.keys(); e.hasMoreElements(); ) {
640+ ClassDeclaration c = (ClassDeclaration)e.nextElement();
641+ ClassDefinition def = c.getClassDefinition(env);
642+
643+ if (!def.subClassOf(env, ignore1)
644+ && !def.subClassOf(env, ignore2)
645+ && def.subClassOf(env, except)) {
646+ Node n = (Node)thrown.get(c);
647+ env.error(n.getWhere(),
648+ "initializer.exception", c.getName());
649+ }
650+ }
651+ }
652+ if (env.dump()) {
653+ getValue().print(System.out);
654+ System.out.println();
655+ }
656+ }
657+ status = getClassDefinition().getError() ? ERROR : CHECKED;
658+ }
659+
660+
661+ // Initializers (static and instance) must be able to complete normally.
662+ if (isInitializer() && vset.isDeadEnd()) {
663+ env.error(where, "init.no.normal.completion");
664+ vset = vset.clearDeadEnd();
665+ }
666+
667+ return vset;
668+ }
669+
670+ // helper to check(): synthesize a missing super() call
671+ private Expression getDefaultSuperCall(Environment env) {
672+ Expression se = null;
673+ ClassDefinition sclass = getClassDefinition().getSuperClass().getClassDefinition();
674+ // does the superclass constructor require an enclosing instance?
675+ ClassDefinition reqc = (sclass == null) ? null
676+ : sclass.isTopLevel() ? null
677+ : sclass.getOuterClass();
678+ ClassDefinition thisc = getClassDefinition();
679+ if (reqc != null && !Context.outerLinkExists(env, reqc, thisc)) {
680+ se = new SuperExpression(where, new NullExpression(where));
681+ env.error(where, "no.default.outer.arg", reqc, getClassDefinition());
682+ }
683+ if (se == null) {
684+ se = new SuperExpression(where);
685+ }
686+ return new MethodExpression(where, se, idInit, new Expression[0]);
687+ }
688+
689+ /**
690+ * Inline the field
691+ */
692+ void inline(Environment env) throws ClassNotFound {
693+ switch (status) {
694+ case PARSED:
695+ check(env);
696+ inline(env);
697+ break;
698+
699+ case CHECKED:
700+ if (env.dump()) {
701+ System.out.println("[inline field " + getClassDeclaration().getName() + "." + getName() + "]");
702+ }
703+ status = INLINING;
704+ env = new Environment(env, this);
705+
706+ if (isMethod()) {
707+ if ((!isNative()) && (!isAbstract())) {
708+ Statement s = (Statement)getValue();
709+ Context ctx = new Context((Context)null, this);
710+ for (Enumeration e = args.elements() ; e.hasMoreElements() ;) {
711+ LocalMember local = (LocalMember)e.nextElement();
712+ ctx.declare(env, local);
713+ }
714+ setValue(s.inline(env, ctx));
715+ }
716+ } else if (isInnerClass()) {
717+ // some classes are checked and inlined separately
718+ ClassDefinition nc = getInnerClass();
719+ if (nc instanceof SourceClass && !nc.isLocal()
720+ && nc.isInsideLocal()) {
721+ status = INLINING;
722+ ((SourceClass)nc).inlineLocalClass(env);
723+ }
724+ status = INLINED;
725+ break;
726+ } else {
727+ if (getValue() != null) {
728+ Context ctx = new Context((Context)null, this);
729+ if (!isStatic()) {
730+ // Cf. "thisArg" in SourceClass.checkMembers().
731+ Context ctxInst = new Context(ctx, this);
732+ LocalMember thisArg =
733+ ((SourceClass)clazz).getThisArgument();
734+ ctxInst.declare(env, thisArg);
735+ setValue(((Expression)getValue())
736+ .inlineValue(env, ctxInst));
737+ } else {
738+ setValue(((Expression)getValue())
739+ .inlineValue(env, ctx));
740+ }
741+ }
742+ }
743+ if (env.dump()) {
744+ System.out.println("[inlined field " + getClassDeclaration().getName() + "." + getName() + "]");
745+ if (getValue() != null) {
746+ getValue().print(System.out);
747+ System.out.println();
748+ } else {
749+ System.out.println("<empty>");
750+ }
751+ }
752+ status = INLINED;
753+ break;
754+ }
755+ }
756+
757+ /**
758+ * Get the value of the field (or null if the value can't be determined)
759+ */
760+ public Node getValue(Environment env) throws ClassNotFound {
761+ Node value = getValue();
762+ if (value != null && status != INLINED) {
763+ // be sure to get the imports right:
764+ env = ((SourceClass)clazz).setupEnv(env);
765+ inline(env);
766+ value = (status == INLINED) ? getValue() : null;
767+ }
768+ return value;
769+ }
770+
771+ public boolean isInlineable(Environment env, boolean fromFinal) throws ClassNotFound {
772+ if (super.isInlineable(env, fromFinal)) {
773+ getValue(env);
774+ return (status == INLINED) && !getClassDefinition().getError();
775+ }
776+ return false;
777+ }
778+
779+
780+ /**
781+ * Get the initial value of the field
782+ */
783+ public Object getInitialValue() {
784+ if (isMethod() || (getValue() == null) || (!isFinal()) || (status != INLINED)) {
785+ return null;
786+ }
787+ return ((Expression)getValue()).getValue();
788+ }
789+
790+ /**
791+ * Generate code
792+ */
793+ public void code(Environment env, Assembler asm) throws ClassNotFound {
794+ switch (status) {
795+ case PARSED:
796+ check(env);
797+ code(env, asm);
798+ return;
799+
800+ case CHECKED:
801+ inline(env);
802+ code(env, asm);
803+ return;
804+
805+ case INLINED:
806+ // Actually generate code
807+ if (env.dump()) {
808+ System.out.println("[code field " + getClassDeclaration().getName() + "." + getName() + "]");
809+ }
810+ if (isMethod() && (!isNative()) && (!isAbstract())) {
811+ env = new Environment(env, this);
812+ Context ctx = new Context((Context)null, this);
813+ Statement s = (Statement)getValue();
814+
815+ for (Enumeration e = args.elements() ; e.hasMoreElements() ; ) {
816+ LocalMember f = (LocalMember)e.nextElement();
817+ ctx.declare(env, f);
818+ //ctx.declare(env, (LocalMember)e.nextElement());
819+ }
820+
821+ /*
822+ if (isConstructor() && ((s == null) || (s.firstConstructor() == null))) {
823+ ClassDeclaration c = getClassDefinition().getSuperClass();
824+ if (c != null) {
825+ MemberDefinition field = c.getClassDefinition(env).matchMethod(env, getClassDefinition(), idInit);
826+ asm.add(getWhere(), opc_aload, new Integer(0));
827+ asm.add(getWhere(), opc_invokespecial, field);
828+ asm.add(getWhere(), opc_pop);
829+ }
830+
831+ // Output initialization code
832+ for (MemberDefinition f = getClassDefinition().getFirstMember() ; f != null ; f = f.getNextMember()) {
833+ if (!f.isStatic()) {
834+ f.codeInit(env, ctx, asm);
835+ }
836+ }
837+ }
838+ */
839+ if (s != null) {
840+ s.code(env, ctx, asm);
841+ }
842+ if (getType().getReturnType().isType(TC_VOID) && !isInitializer()) {
843+ asm.add(getWhere(), opc_return, true);
844+ }
845+ }
846+ return;
847+ }
848+ }
849+
850+ public void codeInit(Environment env, Context ctx, Assembler asm) throws ClassNotFound {
851+ if (isMethod()) {
852+ return;
853+ }
854+ switch (status) {
855+ case PARSED:
856+ check(env);
857+ codeInit(env, ctx, asm);
858+ return;
859+
860+ case CHECKED:
861+ inline(env);
862+ codeInit(env, ctx, asm);
863+ return;
864+
865+ case INLINED:
866+ // Actually generate code
867+ if (env.dump()) {
868+ System.out.println("[code initializer " + getClassDeclaration().getName() + "." + getName() + "]");
869+ }
870+ if (getValue() != null) {
871+ Expression e = (Expression)getValue();
872+ // The JLS Section 8.5 specifies that static (non-final)
873+ // initializers should be executed in textual order. Eliding
874+ // initializations to default values can interfere with this,
875+ // so the tests for !e.equalsDefault() have been eliminated,
876+ // below.
877+ if (isStatic()) {
878+ if (getInitialValue() == null) {
879+ // removed: && !e.equalsDefault()) {
880+ e.codeValue(env, ctx, asm);
881+ asm.add(getWhere(), opc_putstatic, this);
882+ }
883+ } else { // removed: if (!e.equalsDefault()) {
884+ // This code doesn't appear to be reached for
885+ // instance initializers. Code for these is generated
886+ // in the makeVarInits() method of the class
887+ // MethodExpression.
888+ asm.add(getWhere(), opc_aload, new Integer(0));
889+ e.codeValue(env, ctx, asm);
890+ asm.add(getWhere(), opc_putfield, this);
891+ }
892+ }
893+ return;
894+ }
895+ }
896+
897+ /**
898+ * Print for debugging
899+ */
900+ public void print(PrintStream out) {
901+ super.print(out);
902+ if (getValue() != null) {
903+ getValue().print(out);
904+ out.println();
905+ }
906+ }
907+}