Skip to content

Commit 637fbbd

Browse files
committed
[GR-26178] Scope finder is not able to find all scopes.
PullRequest: graalpython/1284
2 parents 12ec0d4 + e7cdbc9 commit 637fbbd

File tree

70 files changed

+2877
-1874
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+2877
-1874
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/parser/sst/SSTCheckOffsetVisitor.java

Lines changed: 728 additions & 0 deletions
Large diffs are not rendered by default.

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/ClassDefTests.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ public void decorator02() throws Exception {
167167
"class foo():pass");
168168
}
169169

170+
@Test
171+
public void decorator03() throws Exception {
172+
checkScopeAndTree("class C(object):\n" +
173+
" @staticmethod\n" +
174+
" def foo(): return 42\n");
175+
}
176+
170177
@Test
171178
public void classDoc01() throws Exception {
172179
checkTreeResult(

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/ParserTestBase.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.oracle.graal.python.PythonLanguage;
4444
import com.oracle.graal.python.parser.PythonParserImpl;
4545
import com.oracle.graal.python.parser.ScopeInfo;
46+
import com.oracle.graal.python.parser.sst.SSTCheckOffsetVisitor;
4647
import com.oracle.graal.python.parser.sst.SSTNode;
4748
import com.oracle.graal.python.runtime.PythonContext;
4849
import com.oracle.graal.python.runtime.PythonParser;
@@ -97,6 +98,7 @@ public Node parse(String src, String moduleName, PythonParser.ParserMode mode, F
9798
PythonParser parser = context.getCore().getParser();
9899
Node result = ((PythonParserImpl) parser).parseN(mode, context.getCore(), source, fd, null);
99100
lastGlobalScope = ((PythonParserImpl) parser).getLastGlobaScope();
101+
lastSST = ((PythonParserImpl) parser).getLastSST();
100102
return result;
101103
}
102104

@@ -260,6 +262,12 @@ public void checkScopeResult(String source, PythonParser.ParserMode mode) throws
260262
assertDescriptionMatches(scopes.toString(), goldenScopeFile);
261263
}
262264

265+
public void checkSSTNodeOffsets(SSTNode node) {
266+
SSTCheckOffsetVisitor checker = new SSTCheckOffsetVisitor(node);
267+
boolean result = node.accept(checker);
268+
assertTrue(checker.getMessage(), result);
269+
}
270+
263271
protected String printTreeToString(Node node) {
264272
ParserTreePrinter visitor = new ParserTreePrinter();
265273
visitor.printFormatStringLiteralDetail = printFormatStringLiteralValues;
@@ -428,6 +436,7 @@ private static String lineSeparator(int number) {
428436

429437
public void checkScopeAndTree(String source, PythonParser.ParserMode mode) throws Exception {
430438
checkScopeResult(source, mode);
439+
checkSSTNodeOffsets(lastSST);
431440
checkTreeResult(source, mode);
432441
}
433442

@@ -437,10 +446,12 @@ public void checkScopeAndTree(String source) throws Exception {
437446

438447
public void checkTreeResult(String source) throws Exception {
439448
checkTreeResult(source, PythonParser.ParserMode.File);
449+
checkSSTNodeOffsets(lastSST);
440450
}
441451

442452
public void checkScopeAndTreeFromFile(File testFile) throws Exception {
443453
checkScopeFromFile(testFile, true);
454+
checkSSTNodeOffsets(lastSST);
444455
checkTreeFromFile(testFile, true);
445456
}
446457
}

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/RuntimeFileTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -165,5 +165,6 @@ private void checkScopeAndTree() throws Exception {
165165
File testFile = getTestFileFromTestAndTestMethod();
166166
checkScopeFromFile(testFile, true);
167167
checkTreeFromFile(testFile, true);
168+
checkSSTNodeOffsets(getLastSST());
168169
}
169170
}

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/SSTNodeWithScopeFinderTest.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,47 @@ public void ifTest() throws Exception {
9898
checkFinder(code, code.indexOf("def fn3"), code.indexOf("30") + 3, false);
9999
}
100100

101+
@Test
102+
public void decoratedTest() throws Exception {
103+
String code = "@mydecorator(lambda : 10)\n" +
104+
"def fn():\n" +
105+
" pass\n";
106+
checkFinder(code, code.indexOf("lambda"), code.indexOf("10") + 2, true);
107+
checkFinder(code, code.indexOf("def fn"), code.indexOf("pass") + 5, false);
108+
}
109+
110+
@Test
111+
public void lambdaInLambda() throws Exception {
112+
String code = "l4 = lambda x = lambda y = lambda z=1 : z : y() : x()";
113+
checkFinder(code, code.indexOf("lambda x"), code.indexOf("x()") + 3, true);
114+
checkFinder(code, code.indexOf("lambda y"), code.indexOf("y()") + 3, true);
115+
checkFinder(code, code.indexOf("lambda z"), code.indexOf("z :") + 1, true);
116+
}
117+
118+
@Test
119+
public void lambdaInCall01() throws Exception {
120+
String code = "fn(lambda: 20)";
121+
checkFinder(code, code.indexOf("lambda"), code.indexOf("20") + 2, true);
122+
}
123+
124+
@Test
125+
public void lambdaInCall02() throws Exception {
126+
String code = "fn(a = lambda: 20)";
127+
checkFinder(code, code.indexOf("lambda"), code.indexOf("20") + 2, true);
128+
}
129+
130+
@Test
131+
public void funcDefTest01() throws Exception {
132+
String code = "def fn (filter = lambda x: x > 4): pass";
133+
checkFinder(code, code.indexOf("lambda"), code.indexOf("4") + 1, true);
134+
}
135+
136+
@Test
137+
public void with01() throws Exception {
138+
String code = "with lambda: fn() as michael: pass";
139+
checkFinder(code, code.indexOf("lambda"), code.indexOf("fn()") + 4, true);
140+
}
141+
101142
private void checkFinder(String code, int startOffset, int endOffset, boolean isLambda) {
102143
SSTNode result = findNodeWithScope(code, startOffset, endOffset);
103144
Assert.assertNotNull("No node with scope was found ", result);

graalpython/com.oracle.graal.python.test/testData/goldenFiles/AwaitAndAsyncTests/asyncWith02.tast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ ModuleRootNode Name: <module 'asyncWith02'> SourceSection: [0,47]`async def f():
3535
BlockNode SourceSection: None
3636
FunctionBodyNode SourceSection: [22,47]`with a as b, c as d:...`
3737
WithNode SourceSection: [22,47]`with a as b, c as d:...`
38-
WithNode SourceSection: None
38+
WithNode SourceSection: [35,47]`c as d: pass`
3939
ExpressionStatementNode SourceSection: [43,47]`pass`
4040
EmptyNode SourceSection: [43,47]`pass`
4141
WriteLocalVariableNodeGen SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/with02.tast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ModuleRootNode Name: <module 'with02'> SourceSection: [0,31]`with A() as a, B()
1010
EmptyNode SourceSection: None
1111
SideEffect:
1212
WithNode SourceSection: [0,31]`with A() as a, B() a...`
13-
WithNode SourceSection: None
13+
WithNode SourceSection: [15,31]`B() as b:↵ pass`
1414
ExpressionStatementNode SourceSection: [27,31]`pass`
1515
EmptyNode SourceSection: [27,31]`pass`
1616
WriteNameNodeGen SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/BasicTests/with04.tast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ ModuleRootNode Name: <module 'with04'> SourceSection: [0,45]`def fn():↵ with
3535
BlockNode SourceSection: None
3636
FunctionBodyNode SourceSection: [12,45]`with A() as a, B() a...`
3737
WithNode SourceSection: [12,45]`with A() as a, B() a...`
38-
WithNode SourceSection: None
38+
WithNode SourceSection: [27,45]`B() as b:↵ pass`
3939
ExpressionStatementNode SourceSection: [41,45]`pass`
4040
EmptyNode SourceSection: [41,45]`pass`
4141
WriteLocalVariableNodeGen SourceSection: None
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Scope: []
2+
Kind: Module
3+
FrameDescriptor: Empty
4+
CellVars: Empty
5+
FreeVars: Empty
6+
Scope: C
7+
Kind: Class
8+
FrameDescriptor: [foo]
9+
CellVars: Empty
10+
FreeVars: Empty
11+
Scope: foo
12+
Kind: Function
13+
FrameDescriptor: [<return_val>]
14+
CellVars: Empty
15+
FreeVars: Empty
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
ModuleRootNode Name: <module 'decorator03'> SourceSection: [0,60]`class C(object):↵ ...`
2+
Signature: varArgs=False, varKeywordArgs=False, noArguments=True, positionalOnly=True, requiresKeywordArgs=False
3+
FreeVars: None
4+
NeedsCellFrame: False
5+
FrameDescriptor: Empty
6+
Documentation: None
7+
InnerRootNode SourceSection: [0,60]`class C(object):↵ ...`
8+
ExpressionWithSideEffect SourceSection: [0,60]`class C(object):↵ ...`
9+
Expression:
10+
EmptyNode SourceSection: None
11+
SideEffect:
12+
WriteNameNodeGen SourceSection: [0,60]`class C(object):↵ ...`
13+
Identifier: C
14+
PythonCallTernary SourceSection: [0,60]`class C(object):↵ ...`
15+
CallTernaryMethodNodeGen SourceSection: None
16+
GetCallAttributeNodeGen SourceSection: None
17+
BuiltinsLiteralNode SourceSection: None
18+
FunctionDefinitionNode Name: C SourceSection: None
19+
Arguments: None
20+
KwArguments: None
21+
Documentation: None
22+
FreeVarSlots: None
23+
ExecutionSlots:
24+
FreeVarsSlots: None
25+
CellVarsSlots: None
26+
ClassBodyRootNode SourceSection: [0,60]`class C(object):↵ ...`
27+
Name: C
28+
Signature: varArgs=False, varKeywordArgs=False, noArguments=False, positionalOnly=True, requiresKeywordArgs=False
29+
Param Names: namespace
30+
CelVars: None
31+
FreeVars: None
32+
NeedsCellFrame: False
33+
FrameDescriptor: 1 slots [foo]
34+
ExecutionSlots:
35+
FreeVarsSlots: None
36+
CellVarsSlots: None
37+
InnerRootNode SourceSection: [0,60]`class C(object):↵ ...`
38+
ReturnTargetNode SourceSection: [0,60]`class C(object):↵ ...`
39+
Body: BlockNode SourceSection: None
40+
ClassDefinitionPrologueNode SourceSection: None
41+
QualName: C
42+
ReadGlobalOrBuiltinNodeGen SourceSection: None
43+
Identifier: __name__
44+
ReadAttributeFromObjectNotTypeNodeGen SourceSection: None
45+
ReadIndexedArgumentNodeGen SourceSection: None
46+
Index: 0
47+
SetItemIfNotPresentNodeGen SourceSection: None
48+
SetItemNodeGen SourceSection: None
49+
FunctionBodyNode SourceSection: [21,60]`@staticmethod↵ de...`
50+
SetItemNodeGen SourceSection: [21,60]`@staticmethod↵ de...`
51+
ArgumentExpressionNode SourceSection: None
52+
ReadIndexedArgumentNodeGen SourceSection: None
53+
Index: 0
54+
StringLiteralNode SourceSection: None
55+
PythonCallUnary SourceSection: [21,34]`@staticmethod`
56+
CallUnaryMethodNodeGen SourceSection: None
57+
ReadClassAttributeNodeGen SourceSection: [21,34]`@staticmethod`
58+
GetItemNodeGen SourceSection: None
59+
ArgumentExpressionNode SourceSection: None
60+
ReadIndexedArgumentNodeGen SourceSection: None
61+
Index: 0
62+
StringLiteralNode SourceSection: None
63+
ReadGlobalOrBuiltinNodeGen SourceSection: None
64+
Identifier: staticmethod
65+
ReadAttributeFromObjectNotTypeNodeGen SourceSection: None
66+
FunctionDefinitionNode Name: foo SourceSection: None
67+
Arguments: None
68+
KwArguments: None
69+
Documentation: None
70+
FreeVarSlots: None
71+
ExecutionSlots:
72+
FreeVarsSlots: None
73+
CellVarsSlots: None
74+
FunctionRootNode SourceSection: [39,60]`def foo(): return 42...`
75+
Name: foo
76+
Signature: varArgs=False, varKeywordArgs=False, noArguments=True, positionalOnly=True, requiresKeywordArgs=False
77+
CelVars: None
78+
FreeVars: None
79+
NeedsCellFrame: False
80+
FrameDescriptor: 1 slots [<return_val>]
81+
ExecutionSlots:
82+
FreeVarsSlots: None
83+
CellVarsSlots: None
84+
InnerRootNode SourceSection: [39,60]`def foo(): return 42...`
85+
ReturnTargetNode SourceSection: [39,60]`def foo(): return 42...`
86+
Body: BlockNode SourceSection: None
87+
BlockNode SourceSection: None
88+
FunctionBodyNode SourceSection: [50,59]`return 42`
89+
FrameReturnNode SourceSection: [50,59]`return 42`
90+
WriteLocalVariableNodeGen SourceSection: None
91+
Identifier: <return_val>
92+
WriteLocalFrameSlotNodeGen SourceSection: None
93+
Frame: [0,<return_val>,Illegal]
94+
IntegerLiteralNode SourceSection: [57,59]`42`
95+
Value: 42
96+
Return Expresssion: ReadLocalVariableNode SourceSection: None
97+
Frame: [0,<return_val>,Illegal]
98+
ReadVariableFromFrameNodeGen SourceSection: None
99+
Return Expresssion: ObjectLiteralNode SourceSection: None
100+
StringLiteralNode SourceSection: None
101+
ReadNameNodeGen SourceSection: [8,14]`object`
102+
Identifier: object
103+
IsBuiltinClassProfile SourceSection: None
104+
CachedDispatchFirst SourceSection: None

0 commit comments

Comments
 (0)