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

// $Id$

package scalac.symtab.classfile;

import java.io.IOException;
import java.util.Iterator;
import java.util.HashMap;
import java.util.HashSet;

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.SourceRepresentation;

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

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

    /** The JVM class file parser */
    private final ClassParser classCompletion;

    /** The CLR package parser */
    private final CLRPackageParser importer;

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

    /** Initializes this instance. */
    public PackageParser(Global global) {
        super(global);
        this.classCompletion = new ClassParser(global);
	this.importer = (global.target == global.TARGET_MSIL)
	    ? CLRPackageParser.create(global) : null;
	if (global.reporter.verbose)
	    global.reporter.inform("classpath = " + global.classPath);
    }

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

    /** Completes the package symbol by loading all its members. */
    protected String doComplete(Symbol peckage) {
	boolean isRoot = peckage.isRoot();
        String dirname = isRoot ? null
            : SourceRepresentation.externalizeFileName(peckage, "/");

        // collect JVM and source members
        HashMap sources = new HashMap();
        HashMap classes = new HashMap();
        HashSet packages = new HashSet();
        String[] base = global.classPath.components();
        for (int i = 0; i < base.length; i++) {
            AbstractFile dir = AbstractFile.open(base[i], dirname);
            if (dir == null) continue;
            try {
                String[] filenames = dir.list();
                if (filenames == null) continue;
                for (int j = 0; j < filenames.length; j++) {
                    String fname = filenames[j];
                    if (fname.endsWith("/") && !fname.equals("META-INF/")) {
                        String name = fname.substring(0, fname.length() - 1);
                        packages.add(name);
                        continue;
                    }
                    if (!isRoot && fname.endsWith(".class")) {
                        String name = fname.substring(0, fname.length() - 6);
                        if (!classes.containsKey(name))
                            classes.put(name, dir.open(fname));
                        continue;
                    }
                    if (!isRoot && fname.endsWith(".scala")) {
                        String name = fname.substring(0, fname.length() - 6);
                        if (!sources.containsKey(name))
                            sources.put(name, dir.open(fname));
                        continue;
                    }
                }
            } catch (IOException exception) {
                if (global.debug) exception.printStackTrace();
                continue;
            }
	}

        // 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();
            SourceCompleter completer = new SourceCompleter(global);
            peckage.newLoadedClass(0, classname, completer, members);
        }
        for (Iterator i = classes.entrySet().iterator(); i.hasNext(); ) {
            HashMap.Entry entry = (HashMap.Entry)i.next();
            String name = (String)entry.getKey();
            AbstractFile cfile = (AbstractFile)entry.getValue();
            packages.remove(name);
            Name classname = Name.fromString(name).toTypeName();
            peckage.newLoadedClass(JAVA, classname, classCompletion, members);
        }
        for (Iterator i = packages.iterator(); i.hasNext(); ) {
            String name = (String)i.next();
            peckage.newLoadedPackage(Name.fromString(name), this, members);
        }

        // collect and create CLR members
        if (importer != null) importer.importCLRTypes(peckage, members, this);

        // initialize package
        peckage.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, peckage));
        return dirname == null ? "anonymous package" : "package '"+dirname+"'";
    }

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