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

package scalac.symtab.classfile;

import scalac.*;
import scalac.symtab.*;
import scalac.util.*;
import java.io.*;

public class PackageParser extends Type.LazyType {

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

    /** the class parser
     */
    public ClassParser classCompletion;

    public PackageParser(Global global) {
        this.global = global;
        this.classCompletion = new ClassParser(global);
    }

    /** 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();
        if (name.length() == 0) {
            // includeMembers(AbstractFile.open(null, "."), p, members, false);
        } else {
            dirname = externalizeFileName(name);
	    assert !dirname.startsWith("com") : p;//debug
            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);
	}
        p.setInfo(Type.compoundType(Type.EMPTY_ARRAY, members, p));
        if (dirname == null)
            dirname = "anonymous package";
        global.operation("scanned " + dirname + " in " +
                    (System.currentTimeMillis() - msec) + "ms");
    }

    /** read directory of a classpath directory and include members
     *  in package/module scope
     */
    protected void includeMembers(AbstractFile dir, Symbol p, Scope locals,
				  boolean inclClasses) {
        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];
                if (inclClasses && fname.endsWith(".class")) {
                    Name n = Name.fromString(fname.substring(0, fname.length() - 6))
			.toTypeName();
		    ClassSymbol clazz = new ClassSymbol(n, p, classCompletion);
		    clazz.constructor().setInfo(
			classCompletion.staticsParser(clazz));
		    // enter class
		    locals.enter(clazz);
		    locals.enter(clazz.constructor());
		    // 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());
		    }
                } 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);
                    }
                } else if (fname.endsWith(".scala")) {
                    Name n = Name.fromString(fname.substring(0, fname.length() - 6))
			.toTypeName();
                    if (locals.lookup(n) == Symbol.NONE) {
                        SourceCompleter completer = new SourceCompleter(global,
                            dir.getPath() + File.separatorChar + fname);
                        ClassSymbol clazz = new ClassSymbol(n, p, completer);
                        clazz.constructor().setInfo(completer);
			clazz.module().setInfo(completer);
                        // enter class
                        locals.enter(clazz);
			locals.enter(clazz.constructor());
			locals.enter(clazz.module());
                    }
                }
            }
        } catch (IOException e) {
        }
    }

    /** return external representation of file name s,
     *  converting '.' to File.separatorChar
     */

    public String externalizeFileName(Name n) {
        if ((n == null) || (n.length() == 0))
            return ".";
        byte[] ascii = n.toAscii();
        String s = SourceRepresentation.ascii2string(
            ascii, 0, ascii.length);
        return s.replace('.', File.separatorChar);
    }
}