summaryrefslogtreecommitdiff
path: root/sources/scalac/symtab/classfile/PackageParser.java
blob: 415ee7a3b454acefbedfdaff2785a6aac8edf9fb (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
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.symtab.classfile;

import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;

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 */
    protected final AbstractFile directory;

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

    /** Initializes this instance. */
    public PackageParser(Global global, AbstractFile directory) {
        super(global);
        this.directory = directory;
    }

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

    protected java.util.Map sources = new HashMap();
    protected java.util.Map classes = new HashMap();
    protected java.util.Map packages = new HashMap();

    // collect JVM and source members
    protected void preInitialize(Symbol root, boolean loadClassfiles) {
	boolean isRoot = root.isRoot();
        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 && loadClassfiles && 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;
            }
	}
    }

    /** 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();
        preInitialize(peckage, true);

        // 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 (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);
            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);
        }

        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);
        }

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

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