mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 16:06:39 +03:00
Fixed a few bugs in f-string parsing and added minimal support for f-string format directives.
This commit is contained in:
parent
38a038c1ae
commit
d0a7771090
@ -18,14 +18,14 @@ import { PythonVersion } from '../common/pythonVersion';
|
||||
import { TextRange } from '../common/textRange';
|
||||
import { AssertNode, AssignmentNode, AugmentedAssignmentExpressionNode,
|
||||
BinaryExpressionNode, BreakNode, CallExpressionNode, ClassNode, ConstantNode,
|
||||
DecoratorNode, DelNode, ErrorExpressionNode, ExceptNode, ExpressionNode, ForNode,
|
||||
FunctionNode, IfNode, ImportAsNode, ImportFromNode, IndexExpressionNode,
|
||||
LambdaNode, ListComprehensionForNode, ListComprehensionNode, ListNode,
|
||||
MemberAccessExpressionNode, ModuleNode, NameNode, ParameterCategory, ParseNode,
|
||||
RaiseNode, ReturnNode, SliceExpressionNode, StringListNode, SuiteNode,
|
||||
TernaryExpressionNode, TryNode, TupleExpressionNode, TypeAnnotationExpressionNode,
|
||||
UnaryExpressionNode, UnpackExpressionNode, WhileNode, WithNode, YieldExpressionNode,
|
||||
YieldFromExpressionNode } from '../parser/parseNodes';
|
||||
DecoratorNode, DelNode, ErrorExpressionNode, ExceptNode, ExpressionNode, FormatStringNode,
|
||||
ForNode, FunctionNode, IfNode, ImportAsNode, ImportFromNode,
|
||||
IndexExpressionNode, LambdaNode, ListComprehensionForNode, ListComprehensionNode,
|
||||
ListNode, MemberAccessExpressionNode, ModuleNode, NameNode, ParameterCategory,
|
||||
ParseNode, RaiseNode, ReturnNode, SliceExpressionNode, StringListNode,
|
||||
SuiteNode, TernaryExpressionNode, TryNode, TupleExpressionNode,
|
||||
TypeAnnotationExpressionNode, UnaryExpressionNode, UnpackExpressionNode, WhileNode,
|
||||
WithNode, YieldExpressionNode, YieldFromExpressionNode } from '../parser/parseNodes';
|
||||
import { KeywordType } from '../parser/tokenizerTypes';
|
||||
import { ScopeUtils } from '../scopeUtils';
|
||||
import { AnalyzerFileInfo } from './analyzerFileInfo';
|
||||
@ -1085,6 +1085,14 @@ export class TypeAnalyzer extends ParseTreeWalker {
|
||||
return true;
|
||||
}
|
||||
|
||||
visitFormatString(node: FormatStringNode): boolean {
|
||||
node.expressions.forEach(formatExpr => {
|
||||
this._getTypeOfExpression(formatExpr.expression, true, true);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
visitName(node: NameNode) {
|
||||
const nameValue = node.nameToken.value;
|
||||
const symbolInScope = this._currentScope.lookUpSymbolRecursive(nameValue);
|
||||
|
@ -789,7 +789,7 @@ export class FormatStringExpression {
|
||||
}
|
||||
|
||||
export class FormatStringNode extends ExpressionNode {
|
||||
readonly nodeType = ParseNodeType.String;
|
||||
readonly nodeType = ParseNodeType.FormatString;
|
||||
token: StringToken;
|
||||
value: string;
|
||||
hasUnescapeErrors: boolean;
|
||||
|
@ -2339,10 +2339,23 @@ export class Parser {
|
||||
|
||||
for (let segment of unescapedResult.formatStringSegments) {
|
||||
if (segment.isExpression) {
|
||||
let parser = new Parser();
|
||||
let parseResults = parser.parseTextExpression(this._fileContents!,
|
||||
stringToken.start + stringToken.prefixLength + stringToken.quoteMarkLength + segment.offset,
|
||||
segment.length, this._parseOptions);
|
||||
const parser = new Parser();
|
||||
|
||||
// Determine if we need to truncate the expression because it
|
||||
// contains formatting directives that start with a ! or :.
|
||||
let segmentExprLength = segment.length;
|
||||
const bangIndex = segment.value.search(/\![^=]/);
|
||||
if (bangIndex >= 0) {
|
||||
segmentExprLength = Math.min(segmentExprLength, bangIndex);
|
||||
}
|
||||
const colonIndex = segment.value.search(/\:/);
|
||||
if (colonIndex >= 0) {
|
||||
segmentExprLength = Math.min(segmentExprLength, colonIndex);
|
||||
}
|
||||
|
||||
const parseResults = parser.parseTextExpression(this._fileContents!,
|
||||
stringToken.start + stringToken.prefixLength + stringToken.quoteMarkLength +
|
||||
segment.offset, segmentExprLength, this._parseOptions);
|
||||
|
||||
parseResults.diagnostics.forEach(diag => {
|
||||
const textRangeStart = (diag.range ?
|
||||
|
@ -16,3 +16,9 @@ c = f"hello { 1 "
|
||||
|
||||
# Test f-string with double braces.
|
||||
d = f"hello {{{1}}}"
|
||||
|
||||
# Test f-string with formatting directives.
|
||||
e = f"hello { 2 != 3 !r:2 }"
|
||||
|
||||
# Test f-string with formatting directives.
|
||||
f = f"hello { 2 != 3 :3 }"
|
||||
|
Loading…
Reference in New Issue
Block a user