-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add inline provider * add inlineProvider * Add inlie provider * Add tests * fix import * fix lint * Update inline function to remove strins values * Add unit test for class type * fix merge
- Loading branch information
1 parent
481ccdb
commit 695d259
Showing
6 changed files
with
421 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
src/extension/debugger/inlineValue/pythonInlineValueProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT license. | ||
|
||
import { | ||
InlineValue, | ||
InlineValueContext, | ||
InlineValuesProvider, | ||
Range, | ||
TextDocument, | ||
InlineValueVariableLookup, | ||
InlineValueEvaluatableExpression, | ||
} from 'vscode'; | ||
import { customRequest } from '../../common/vscodeapi'; | ||
|
||
export class PythonInlineValueProvider implements InlineValuesProvider { | ||
public async provideInlineValues( | ||
document: TextDocument, | ||
viewPort: Range, | ||
context: InlineValueContext, | ||
): Promise<InlineValue[]> { | ||
let scopesRequest = await customRequest('scopes', { frameId: context.frameId }); | ||
let variablesRequest = await customRequest('variables', { | ||
variablesReference: scopesRequest.scopes[0].variablesReference, | ||
}); | ||
|
||
//https://docs.python.org/3/reference/lexical_analysis.html#keywords | ||
const pythonKeywords = [ | ||
'False', | ||
'await', | ||
'else', | ||
'import ', | ||
'pass', | ||
'None', | ||
'break', | ||
'except', | ||
'in', | ||
'raise', | ||
'True', | ||
'class', | ||
'finally', | ||
'is', | ||
'return', | ||
'and', | ||
'continue', | ||
'for', | ||
'lambda', | ||
'try', | ||
'as', | ||
'def', | ||
'from', | ||
'nonlocal', | ||
'while', | ||
'assert', | ||
'del', | ||
'global', | ||
'not', | ||
'with', | ||
'async', | ||
'elif', | ||
'if', | ||
'or', | ||
'yield', | ||
'self', | ||
]; | ||
|
||
const pythonVariables: any[] = variablesRequest.variables | ||
.filter((variable: any) => variable.type) | ||
.map((variable: any) => variable.name); | ||
|
||
let variableRegex = new RegExp( | ||
'(?:self.)?' + //match self. if present | ||
'[a-zA-Z_][a-zA-Z0-9_]*', //math variable name | ||
'g', | ||
); | ||
|
||
const allValues: InlineValue[] = []; | ||
for (let l = viewPort.start.line; l <= viewPort.end.line; l++) { | ||
const line = document.lineAt(l); | ||
// Skip comments | ||
if (line.text.trimStart().startsWith('#')) { | ||
continue; | ||
} | ||
|
||
let code = removeCharsOutsideBraces(line.text); | ||
|
||
for (let match = variableRegex.exec(code); match; match = variableRegex.exec(code)) { | ||
let varName = match[0]; | ||
// Skip python keywords | ||
if (pythonKeywords.includes(varName)) { | ||
continue; | ||
} | ||
if (pythonVariables.includes(varName.split('.')[0])) { | ||
if (varName.includes('self')) { | ||
const rng = new Range(l, match.index, l, match.index + varName.length); | ||
allValues.push(new InlineValueEvaluatableExpression(rng, varName)); | ||
} else { | ||
const rng = new Range(l, match.index, l, match.index + varName.length); | ||
allValues.push(new InlineValueVariableLookup(rng, varName, false)); | ||
} | ||
} | ||
} | ||
} | ||
return allValues; | ||
} | ||
} | ||
|
||
function removeCharsOutsideBraces(code: string): string { | ||
// Regular expression to find Python strings | ||
const stringRegex = /(["'])(?:(?=(\\?))\2.)*?\1/g; | ||
|
||
//Regular expression to match values inside {} | ||
const insideBracesRegex = /{[^{}]*}/g; | ||
|
||
return code.replace(stringRegex, (match) => { | ||
const content = match.slice(1, -1); | ||
|
||
let result = ''; | ||
let tempMatch; | ||
|
||
while ((tempMatch = insideBracesRegex.exec(content)) !== null) { | ||
result += tempMatch[0]; | ||
} | ||
const processedContent = result || content; | ||
|
||
return match[0] + processedContent + match[0]; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
class Person: | ||
def __init__(self, name, age): | ||
self.name = name | ||
self.age = age | ||
|
||
def greet(self): | ||
return f"Hello, my name is {self.name} and I a {self.age} years old." | ||
|
||
person1 = Person("John Doe", 30) | ||
person1.greet() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
var1 = 5 | ||
var2 = 7 | ||
var3 = "hola" | ||
var4 = {"a": 1, "b": 2} | ||
var5 = [1, 2, 3] | ||
var6 =var1 + var2 |
Oops, something went wrong.