summaryrefslogtreecommitdiff
path: root/sources/scalac/symtab/classfile/PackageParser.java
blob: 9d62fb10093d7c03aa6cdf9576116a4a53e4f0a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
**                                                                      **
** $Id$
\*                                                                      */

package scalac.symtab.classfile;

import ch.epfl.lamp.util.*;
import scalac.*;
import scalac.symtab.*;
import scalac.util.*;
import java.io.*;
import java.util.HashMap;

public class PackageParser extends Type.LazyType {

    /** the global compilation environment
     */
    protected Global global;

    /** the class parser
     */
    public ClassParser classCompletion;
    public SymblParser symblCompletion; // provisional

    public PackageParser(Global global) {
        this.global = global;
        this.classCompletion = new ClassParser(global);
	this.symblCompletion = new SymblParser(global); // provisional
	if (global.reporter.verbose)
	    System.out.println("classpath = " + global.classPath);//debug
    }

    /** complete package type symbol p by loading all package members
     */
    public void complete(Symbol p) {
        long msec = System.currentTimeMillis();
        Scope members = new Scope();
        String dirname = null;
        Name name = p.fullName();
	HashMap/*<Symbol, AbstractFile>*/ symFile = new HashMap();
        if (name.length() == 0) {
            // includeMembers(AbstractFile.open(null, "."), p, members, false);
        } else {
            dirname = SourceRepresentation.externalizeFileName(name);
            if (!dirname.endsWith("/"))
                dirname += "/";
        }
        String[] base = global.classPath.components();
        for (int i = 0; i < base.length; i++) {
            includeMembers(
		AbstractFile.open(base[i], dirname),
		p, members, dirname != null, symFile);
	}
        p.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, p));
        if (dirname == null)
            dirname = "anonymous package";
        global.operation("scanned " + dirname + " in " +
                    (System.currentTimeMillis() - msec) + "ms");
    }

    private boolean isMostRecent(AbstractFile f, Symbol previous, HashMap symFile) {
	if (previous == Symbol.NONE || previous.isPackage()) return true;
	if (previous.pos != Position.NOPOS) return false;
	AbstractFile pf = (AbstractFile) symFile.get(previous);
	if (f.getName().endsWith(".scala")) {
	    if (pf.getName().endsWith(".scala")) return false;
	    if (!global.separate) return true;
	}
	if (f.getName().endsWith(".class")) {
	    if (pf.getName().endsWith(".class")) return false;
	    if (!global.separate) return false;
	}
	return f.lastModified() > pf.lastModified();
    }

    /** read directory of a classpath directory and include members
     *  in package/module scope
     */
    protected void includeMembers(AbstractFile dir, Symbol p, Scope locals,
				  boolean inclClasses, HashMap symFile) {
        if (dir == null)
            return;
        String[] filenames = null;
        try {
            if ((filenames = dir.list()) == null)
                return;
            for (int j = 0; j < filenames.length; j++) {
                String fname = filenames[j];
		AbstractFile f = dir.open(fname);
                if (inclClasses && fname.endsWith(".class")) {
                    Name n = Name.fromString(fname.substring(0, fname.length() - 6))
			.toTypeName();
		    if (isMostRecent(f, locals.lookup(n), symFile)) {
		        ClassSymbol clazz = new ClassSymbol(n, p, classCompletion);
			// todo: needed?
		        clazz.allConstructors().setInfo(
			    classCompletion.staticsParser(clazz));
			clazz.module().setInfo(
			    classCompletion.staticsParser(clazz));
		        // enter class
		        locals.enter(clazz);
		        // enter module, except for scala.Object class
		        // todo: why not there also?.
		        if (!(n == Names.Object.toTypeName() &&
			      p.fullName().toTermName() == Names.scala)) {
			    Scope.Entry e = locals.lookupEntry(clazz.module().name);
			    if (e != Scope.Entry.NONE) {
			        // we already have a package of the same name; delete it
			        locals.unlink(e);
			    }
			    locals.enter(clazz.module());
		        }
			symFile.put(clazz, f);
                    }
                } else if (fname.endsWith("/") && !fname.equals("META-INF/")) {
                    Name n = Name.fromString(fname.substring(0, fname.length() - 1));
                    if (locals.lookup(n) == Symbol.NONE) {
                        TermSymbol module = TermSymbol.newJavaPackageModule(n, p, this);
                        locals.enter(module);
			//todo: moduleClass needs to be entered?
			locals.enter(module.moduleClass());
		    }

/*
		} else if (inclClasses && fname.endsWith(".symbl")) {
		    //todo: compare dates between symbl and scala.
                    Name n = Name.fromString(fname.substring(0, fname.length() - 6))
			.toTypeName();
		    Symbol sym = locals.lookup(n);
		    if (sym == Symbol.NONE ||
			sym.isPackage() ||
			sym.rawInfoAt(Symbol.FIRST_ID) instanceof ClassParser &&
			!(sym.rawInfoAt(Symbol.FIRST_ID) instanceof SymblParser)) {
			ClassSymbol clazz = new ClassSymbol(n, p, symblCompletion);
			//todo: needed
			clazz.allConstructors().setInfo(symblCompletion);
			clazz.module().setInfo(symblCompletion);
			locals.enter(clazz);
			locals.enter(clazz.module());
		    }
*/
                } else if (inclClasses && fname.endsWith(".scala")) {
                    Name n = Name.fromString(fname.substring(0, fname.length() - 6))
			.toTypeName();
		    if (isMostRecent(f, locals.lookup(n), symFile)) {
                        SourceCompleter completer = new SourceCompleter(global);
                        ClassSymbol clazz = new ClassSymbol(n, p, completer);
			//todo: needed?
                        clazz.allConstructors().setInfo(completer);
			clazz.module().setInfo(completer);
                        // enter class
                        locals.enter(clazz);
			locals.enter(clazz.module());
			symFile.put(clazz, f);
                    }
                }
            }
        } catch (IOException e) {
        }
    }
}