diff --git a/resources/examples/project1/src/moduleAtRoot13.py b/resources/examples/project1/src/moduleAtRoot13.py index daecf2d..aa4a61d 100644 --- a/resources/examples/project1/src/moduleAtRoot13.py +++ b/resources/examples/project1/src/moduleAtRoot13.py @@ -190,3 +190,18 @@ def function_with_keyword_argument(arg0, arg1=10): variableToAccessInKeywordArgumentCallInParenthesis = 42 function_with_keyword_argument(1, arg1 = (variableToAccessInKeywordArgumentCallInParenthesis)) + +variableToAccessInArraySlice = 5 +arrayToBeAccessedInSlice = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + +def variable_to_access_in_array_slice_1(): + return arrayToBeAccessedInSlice[:variableToAccessInArraySlice] + +def variable_to_access_in_array_slice_2(): + return arrayToBeAccessedInSlice[1:variableToAccessInArraySlice] + +def variable_to_access_in_array_slice_3(): + return arrayToBeAccessedInSlice[::variableToAccessInArraySlice] + +def variable_to_access_in_array_slice_with_parentheses(): + return arrayToBeAccessedInSlice[1:(variableToAccessInArraySlice)] diff --git a/src/Famix-Python-Importer-Tests/FamixPythonProject1Test.class.st b/src/Famix-Python-Importer-Tests/FamixPythonProject1Test.class.st index 7080fed..495e321 100644 --- a/src/Famix-Python-Importer-Tests/FamixPythonProject1Test.class.st +++ b/src/Famix-Python-Importer-Tests/FamixPythonProject1Test.class.st @@ -5569,6 +5569,82 @@ FamixPythonProject1Test >> testReadAccessInANot [ self assert: (module accesses anySatisfy: [ :anAccess | anAccess variable = global ]) ] +{ #category : 'tests - accesses' } +FamixPythonProject1Test >> testReadAccessInArraySlice1 [ + + | global function access | + global := self globalVariableNamed: 'variableToAccessInArraySlice'. + function := self functionNamed: 'variable_to_access_in_array_slice_1'. + + access := (global incomingAccesses select: [ :anAccess | anAccess accessor = function ]) detectMax: [ :anAccess | anAccess sourceAnchor startPos ]. + + self assert: access class equals: FamixPythonAccess. + self assert: access source equals: function. + self assert: access accessor equals: function. + self assert: (access target includes: global). + self assert: access variable equals: global. + self deny: access isWrite. + self assert: access isRead. + self assert: (function accesses anySatisfy: [ :anAccess | anAccess variable = global ]) +] + +{ #category : 'tests - accesses' } +FamixPythonProject1Test >> testReadAccessInArraySlice2 [ + + | global function access | + global := self globalVariableNamed: 'variableToAccessInArraySlice'. + function := self functionNamed: 'variable_to_access_in_array_slice_2'. + + access := (global incomingAccesses select: [ :anAccess | anAccess accessor = function ]) detectMax: [ :anAccess | anAccess sourceAnchor startPos ]. + + self assert: access class equals: FamixPythonAccess. + self assert: access source equals: function. + self assert: access accessor equals: function. + self assert: (access target includes: global). + self assert: access variable equals: global. + self deny: access isWrite. + self assert: access isRead. + self assert: (function accesses anySatisfy: [ :anAccess | anAccess variable = global ]) +] + +{ #category : 'tests - accesses' } +FamixPythonProject1Test >> testReadAccessInArraySlice3 [ + + | global function access | + global := self globalVariableNamed: 'variableToAccessInArraySlice'. + function := self functionNamed: 'variable_to_access_in_array_slice_3'. + + access := (global incomingAccesses select: [ :anAccess | anAccess accessor = function ]) detectMax: [ :anAccess | anAccess sourceAnchor startPos ]. + + self assert: access class equals: FamixPythonAccess. + self assert: access source equals: function. + self assert: access accessor equals: function. + self assert: (access target includes: global). + self assert: access variable equals: global. + self deny: access isWrite. + self assert: access isRead. + self assert: (function accesses anySatisfy: [ :anAccess | anAccess variable = global ]) +] + +{ #category : 'tests - accesses' } +FamixPythonProject1Test >> testReadAccessInArraySliceWithParentheses [ + + | global function access | + global := self globalVariableNamed: 'variableToAccessInArraySlice'. + function := self functionNamed: 'variable_to_access_in_array_slice_with_parentheses'. + + access := (global incomingAccesses select: [ :anAccess | anAccess accessor = function ]) detectMax: [ :anAccess | anAccess sourceAnchor startPos ]. + + self assert: access class equals: FamixPythonAccess. + self assert: access source equals: function. + self assert: access accessor equals: function. + self assert: (access target includes: global). + self assert: access variable equals: global. + self deny: access isWrite. + self assert: access isRead. + self assert: (function accesses anySatisfy: [ :anAccess | anAccess variable = global ]) +] + { #category : 'tests - accesses' } FamixPythonProject1Test >> testReadAccessInAssertStatement [ diff --git a/src/Famix-Python-Importer/FamixPythonVisitor.class.st b/src/Famix-Python-Importer/FamixPythonVisitor.class.st index b4f1dd4..9329e16 100644 --- a/src/Famix-Python-Importer/FamixPythonVisitor.class.st +++ b/src/Famix-Python-Importer/FamixPythonVisitor.class.st @@ -1524,6 +1524,12 @@ FamixPythonVisitor >> visitReturnStatement: aNode [ ^ self visitChildren: aNode ] +{ #category : 'visiting - visitChildren' } +FamixPythonVisitor >> visitSlice: aNode [ + + ^ self visitChildren: aNode +] + { #category : 'visiting - visitChildren' } FamixPythonVisitor >> visitString: aStringNode [ " diff --git a/src/Famix-Python-Importer/FamixTSNodeWrapper.extension.st b/src/Famix-Python-Importer/FamixTSNodeWrapper.extension.st index 830e65e..d4b6a8f 100644 --- a/src/Famix-Python-Importer/FamixTSNodeWrapper.extension.st +++ b/src/Famix-Python-Importer/FamixTSNodeWrapper.extension.st @@ -12,12 +12,17 @@ FamixTSNodeWrapper >> isAccessOrReferenceNode [ "I should return true if an Identifier node represent an access or a reference." (self parent type = #attribute and: [ self parent isInCall ]) ifTrue: [ ^ true ]. - + (self isInField: #value ofParentOfType: #keyword_argument) ifTrue: [ ^ true ]. - ^ #( elif_clause list argument_list return_statement lambda if_statement comparison_operator binary_operator assignment not_operator expression_statement - augmented_assignment unary_operator boolean_operator pair list_splat default_parameter dictionary_splat #if_clause #for_in_clause generator_expression - list_comprehension dictionary_comprehension string_content interpolation subscript tuple expression_list) includes: self parent type + "this is for the case where a slice contains variable wrapped in parenthesis + e.g arr[1:(end)] or arr[1:(((end)))]" + (self parent type = #parenthesized_expression and: [ (self parentOfType: #slice) isNotNil ]) ifTrue: [ ^ true ]. + + ^ #( elif_clause list argument_list return_statement lambda if_statement comparison_operator binary_operator assignment not_operator + expression_statement augmented_assignment unary_operator boolean_operator pair list_splat default_parameter dictionary_splat + #if_clause #for_in_clause generator_expression list_comprehension dictionary_comprehension string_content interpolation subscript + tuple expression_list slice ) includes: self parent type ] { #category : '*Famix-Python-Importer' }