summaryrefslogtreecommitdiff
path: root/sources/scalac/symtab/classfile/PackageParser.java
blob: 710c16ea48db37d8c8f87ba3773e7070bbbd1673 (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
166
167
168
169
170
171
172
173
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.symtab.classfile;

import java.util.Iterator;
import java.util.HashMap;
import java.util.Set;

import scala.tools.util.AbstractFile;
import scala.tools.util.Position;

import scalac.Global;
import scalac.symtab.Scope;
import scalac.symtab.SourceCompleter;
import scalac.symtab.Symbol;
import scalac.symtab.SymbolLoader;
import scalac.symtab.Type;
import scalac.util.Name;
import scalac.util.Debug;

import scalac.symtab.SymbolNameWriter;

/**
 * This class implements a package member loader. It can be used to
 * complete package class symbols.
 */
public class PackageParser extends SymbolLoader {

    //########################################################################
    // Private Fields

    /** The directory to read */
    private final AbstractFile directory;

    /** Are we targeting the MSIL? */
    private boolean forMSIL;

    private final CLRPackageParser clrParser;

    //########################################################################
    // Public Constructors

    /** Initializes this instance. */
    public PackageParser(Global global, AbstractFile directory) {
        super(global);
        this.directory = directory;
	this.forMSIL = global.target == global.TARGET_MSIL;
	this.clrParser = forMSIL ? CLRPackageParser.instance() : null;
    }

    //########################################################################
    // Protected Methods

    /** Completes the package symbol by loading all its members. */
    protected String doComplete(Symbol root) {
        assert root.isRoot() || root.isPackage(): Debug.show(root);
        Symbol peckage = root.isRoot() ? root : root.moduleClass();
        // collect JVM and source members
	boolean isRoot = peckage.isRoot();
        HashMap sources = new HashMap();
        HashMap classes = new HashMap();
        HashMap packages = new HashMap();
        for (Iterator i = directory.list(); i.hasNext(); ) {
            AbstractFile file = (AbstractFile)i.next();
            String filename = file.getName();
            if (file.isDirectory()) {
                if (filename.equals("META-INF")) continue;
                packages.put(filename, file);
                continue;
            }
            if (!isRoot && filename.endsWith(".class")) {
                String name = filename.substring(0, filename.length() - 6);
                if (!classes.containsKey(name)) classes.put(name, file);
                continue;
            }
            if (!isRoot && filename.endsWith(".scala")) {
                String name = filename.substring(0, filename.length() - 6);
                if (!sources.containsKey(name)) sources.put(name, file);
                continue;
            }
	}

	HashMap types = null;
	Set namespaces = null;
	ch.epfl.lamp.compiler.msil.Type type = null;
	if (forMSIL) {
	    types = clrParser.getTypes(peckage);
	    namespaces = clrParser.getNamespaces(peckage);
	}

        // create JVM and source members
        Scope members = new Scope();
        for (Iterator i = sources.entrySet().iterator(); i.hasNext(); ) {
            HashMap.Entry entry = (HashMap.Entry)i.next();
            String name = (String)entry.getKey();
            AbstractFile sfile = (AbstractFile)entry.getValue();
            AbstractFile cfile = (AbstractFile)classes.remove(name);
	    if (forMSIL) {
		type = (ch.epfl.lamp.compiler.msil.Type)types.remove(name);
		if (global.separate && forMSIL && type != null) {
// 		    if (type.Assembly.getFile().lastModified()
// 			> sfile.lastModified()) {
			types.put(name, type);
 			continue;
// 		    }
		}
	    } else if (global.separate && cfile != null) {
                if (cfile.lastModified() > sfile.lastModified()) {
		    classes.put(name, cfile);
		    continue;
                }
            }
            packages.remove(name);
            Name classname = Name.fromString(name).toTypeName();
            SymbolLoader loader = new SourceCompleter(global, sfile);
            peckage.newLoadedClass(0, classname, loader, members);
        }

        for (Iterator i = classes.entrySet().iterator(); i.hasNext(); ) {
            HashMap.Entry entry = (HashMap.Entry)i.next();
            String name = (String)entry.getKey();
	    //assert !types.containsKey(name) : types.get(name);
	    if (!forMSIL || clrParser.shouldLoadClassfile(peckage, name)) {
		AbstractFile cfile = (AbstractFile)entry.getValue();
		packages.remove(name);
		Name classname = Name.fromString(name).toTypeName();
		SymbolLoader loader = new ClassParser(global, cfile);
		peckage.newLoadedClass(JAVA, classname, loader, members);
	    }
        }

	if (forMSIL) {
	    // import the CLR types contained in the package (namespace)
	    for (Iterator i = types.values().iterator(); i.hasNext(); ) {
		type = (ch.epfl.lamp.compiler.msil.Type)i.next();
		clrParser.importType(type, peckage, members);
	    }
	}

        for (Iterator i = packages.entrySet().iterator(); i.hasNext(); ) {
            HashMap.Entry entry = (HashMap.Entry)i.next();
            String name = (String)entry.getKey();
            AbstractFile dfile = (AbstractFile)entry.getValue();
            SymbolLoader loader = new PackageParser(global, dfile);
            peckage.newLoadedPackage(Name.fromString(name), loader, members);
	    if (forMSIL)
		namespaces.remove(name);
        }

	if (forMSIL) {
 	    // import the CLR namespaces contained in the package (namespace)
 	    for (Iterator i = namespaces.iterator(); i.hasNext(); ) {
 		String namespace = (String)i.next();
		Name name = Name.fromString(namespace);
		if (members.lookup(name) == Symbol.NONE) {
		    peckage.newLoadedPackage(name, this, members);
		}
 	    }
	}

        // initialize package
        peckage.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, peckage));
        return "directory path '" + directory + "'";
    }

    //########################################################################
}