-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathNImport.java
More file actions
129 lines (108 loc) · 3.76 KB
/
NImport.java
File metadata and controls
129 lines (108 loc) · 3.76 KB
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
/**
* Copyright 2009, Google Inc. All rights reserved.
* Licensed to PSF under a Contributor Agreement.
*/
package org.python.indexer.ast;
import org.python.indexer.Builtins;
import org.python.indexer.Indexer;
import org.python.indexer.NBinding;
import org.python.indexer.Scope;
import org.python.indexer.types.NModuleType;
import org.python.indexer.types.NType;
import org.python.indexer.types.NUnknownType;
import java.util.List;
public class NImport extends NNode {
static final long serialVersionUID = -2180402676651342012L;
public List<NAlias> aliases; // import foo.bar as bar, ..x.y as y
public NImport(List<NAlias> aliases) {
this(aliases, 0, 1);
}
public NImport(List<NAlias> aliases, int start, int end) {
super(start, end);
this.aliases = aliases;
addChildren(aliases);
}
@Override
public boolean bindsName() {
return true;
}
@Override
protected void bindNames(Scope s) throws Exception {
bindAliases(s, aliases);
}
static void bindAliases(Scope s, List<NAlias> aliases) throws Exception {
NameBinder binder = NameBinder.make();
for (NAlias a : aliases) {
if (a.aname != null) {
binder.bind(s, a.aname, new NUnknownType());
}
}
}
@Override
public NType resolve(Scope s) throws Exception {
Scope scope = s.getScopeSymtab();
for (NAlias a : aliases) {
NType modtype = resolveExpr(a, s);
if (modtype.isModuleType()) {
importName(scope, a, modtype.asModuleType());
}
}
return getType();
}
/**
* Import a module's alias (if present) or top-level name into the current
* scope. Creates references to the other names in the alias.
*
* @param mt the module that is actually bound to the imported name.
* for {@code import x.y.z as foo}, it is {@code z}, a sub-module
* of {@code x.y}. For {@code import x.y.z} it is {@code x}.
*/
private void importName(Scope s, NAlias a, NModuleType mt) throws Exception {
if (a.aname != null) {
if (mt.getFile() != null) {
NameBinder.make().bind(s, a.aname, mt);
} else {
// XXX: seems like the url should be set in loadModule, not here.
// Can't the moduleTable store url-keyed modules too?
s.update(a.aname.id,
new NUrl(Builtins.LIBRARY_URL + mt.getTable().getPath() + ".html"),
mt, NBinding.Kind.SCOPE);
}
}
addReferences(s, a.qname, true/*put top name in scope*/);
}
static void addReferences(Scope s, NQname qname, boolean putTopInScope) {
if (qname == null) {
return;
}
if (!qname.getType().isModuleType()) {
return;
}
NModuleType mt = qname.getType().asModuleType();
String modQname = mt.getTable().getPath();
NBinding mb = Indexer.idx.lookupQname(modQname);
if (mb == null) {
mb = Indexer.idx.moduleTable.lookup(modQname);
}
if (mb == null) {
Indexer.idx.putProblem(qname.getName(), "module not found");
return;
}
Indexer.idx.putLocation(qname.getName(), mb);
// All other references in the file should also point to this binding.
if (putTopInScope && qname.isTop()) {
s.put(qname.getName().id, mb);
}
addReferences(s, qname.getNext(), false);
}
@Override
public String toString() {
return "<Import:" + aliases + ">";
}
@Override
public void visit(NNodeVisitor v) {
if (v.visit(this)) {
visitNodeList(aliases, v);
}
}
}