Skip to content
Open
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
a2fdc89
Change string formatting in Display implementation
Karman-singh15 Nov 21, 2025
26e462d
feat: Improve LSP literal completions by removing quotes when inserti…
Karman-singh15 Nov 22, 2025
bc16325
Merge branch 'facebook:main' into main
Karman-singh15 Nov 22, 2025
44c9c09
test: add 'inserting' field to expected LSP completion results for li…
Karman-singh15 Nov 22, 2025
61847f4
combined the quotes test in completion.rs and remove a no-op
Karman-singh15 Nov 24, 2025
35e07a2
Fix linter warnings for cargo
stroxler Nov 22, 2025
58798ba
Just pass down inferred_from_method as a boolean flag
stroxler Nov 22, 2025
285379f
Combine the top to matches of `calculate_class_field`
stroxler Nov 22, 2025
f4541ac
Inline `check_and_sanitize_type_parameters` into the main match
stroxler Nov 22, 2025
b727739
Track a bug in class field sanitization
stroxler Nov 22, 2025
3012d71
Inline get_class_field_initialization
stroxler Nov 22, 2025
309300c
Inline magic initialization check into the match
stroxler Nov 22, 2025
e16f11f
Get rid of magic initialization for instance methods
stroxler Nov 22, 2025
ea4270e
Trivial restructure of matching code
stroxler Nov 22, 2025
9b549c9
Extract `dataclass_field_initialization` code to a helper
stroxler Nov 22, 2025
f04479a
Vendor typify
Nov 22, 2025
c78f732
preserve quantified information when unpacking quantified type var tuple
yangdanny97 Nov 23, 2025
005801c
Add more info to an `unreachable!` message
rchen152 Nov 24, 2025
59b94ca
Add OutputWithLocations struct.
Nov 24, 2025
d0f3220
Add mock implementation of OutputWithLocations
Nov 24, 2025
7081e24
Update pyrefly version]
Nov 24, 2025
7f4cc24
Implement write_str
Nov 24, 2025
4a2fa2a
Implement write_qname
Nov 24, 2025
ed7a356
Implement write_lit
Nov 24, 2025
4d42f7b
Implement write_targs
Nov 24, 2025
6db8cdf
fix parsing of multi-line parameter descriptions in docstrings #1588 …
asukaminato0721 Nov 24, 2025
3f00984
Implement write_type.
Nov 24, 2025
b242eed
Test that Union types do not split properly.
Nov 24, 2025
e5bf11e
fix unused variable detection for reassignments
kinto0 Nov 24, 2025
4e02534
filter star imports from unused detection
kinto0 Nov 24, 2025
7c365fa
highlight false negative
kinto0 Nov 24, 2025
aeb0c55
bump version
kinto0 Nov 24, 2025
32cfc95
Add test to show the Intersection types do not split properly.
Nov 24, 2025
29bfa47
Create fmt_type_sequence helper function to handle types with separat…
Nov 24, 2025
7aa0e90
Update Union Logic to properly split into parts.
Nov 24, 2025
11c7137
Update intersection types to properly split into parts.
Nov 24, 2025
1ff453d
Add test showing that tuple type does not have a location.
Nov 24, 2025
deb5c23
Add test showing that types from typing.py do not have locations.
Nov 24, 2025
394a6fa
Fix crashes when `yield` or `yield from` appears in type annotations
grievejia Nov 24, 2025
143a3b0
add tests for last diff
kinto0 Nov 24, 2025
7c98ce6
refactor: update `get_callables_from_call` destructuring to include a…
Karman-singh15 Nov 24, 2025
ad4e361
Refactor add_literal_completions to remove in_string check
Karman-singh15 Nov 24, 2025
38fcb67
Merge branch 'facebook:main' into main
Karman-singh15 Nov 24, 2025
b2fe8ee
Merge branch 'facebook:main' into main
Karman-singh15 Nov 25, 2025
64a4af2
added missing call
Karman-singh15 Nov 25, 2025
a4f50d4
updated the duplicate quote test
Karman-singh15 Nov 27, 2025
1851ee7
Merge branch 'main' into main
Karman-singh15 Nov 27, 2025
935f9bc
add optional display name to Type::Union
yangdanny97 Nov 25, 2025
65aef3d
bump ruff packages
yangdanny97 Nov 26, 2025
acc00ad
feat: Improve LSP literal completions by removing quotes when inserti…
Karman-singh15 Nov 22, 2025
f00a366
test: add 'inserting' field to expected LSP completion results for li…
Karman-singh15 Nov 22, 2025
5c8d4f9
Fix linter warnings for cargo
stroxler Nov 22, 2025
c781bfa
Just pass down inferred_from_method as a boolean flag
stroxler Nov 22, 2025
3e803c5
Inline `check_and_sanitize_type_parameters` into the main match
stroxler Nov 22, 2025
5f28775
Inline get_class_field_initialization
stroxler Nov 22, 2025
10ac53c
preserve quantified information when unpacking quantified type var tuple
yangdanny97 Nov 23, 2025
13bb911
Add OutputWithLocations struct.
Nov 24, 2025
6e7d7cb
Update pyrefly version]
Nov 24, 2025
63f86cb
fix parsing of multi-line parameter descriptions in docstrings #1588 …
asukaminato0721 Nov 24, 2025
aa455f5
Implement write_type.
Nov 24, 2025
b26bb7e
fix unused variable detection for reassignments
kinto0 Nov 24, 2025
ef09f28
filter star imports from unused detection
kinto0 Nov 24, 2025
ebadfed
Update Union Logic to properly split into parts.
Nov 24, 2025
08dfad0
Add test showing that tuple type does not have a location.
Nov 24, 2025
6e4267d
Fix crashes when `yield` or `yield from` appears in type annotations
grievejia Nov 24, 2025
02b24ba
add tests for last diff
kinto0 Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions pyrefly/lib/error/expectation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ impl Expectation {
))
} else {
for (line_no, msg) in &self.error {
if !errors.iter().any(|e| {
e.msg().replace("\n", "\\n").contains(msg)
// Compare the raw message and a normalized form to tolerate small
// formatting changes (escaped quotes vs doubled quotes).
let found = errors.iter().any(|e| {
let raw = e.msg().replace("\n", "\\n");
let norm = normalize_message(&raw);
(raw.contains(msg) || norm.contains(msg))
&& e.display_range().start.line_within_file().get() as usize == *line_no
}) {
});
if !found {
return Err(anyhow::anyhow!(
"Expectations failed for {}: can't find error (line {line_no}): {msg}",
self.module.path()
Expand All @@ -57,3 +62,9 @@ impl Expectation {
}
}
}

fn normalize_message(s: &str) -> String {
s.replace("\\'", "'") // unescape single quotes
// keep double-quote escapes as-is
.replace("''", "'") // collapse doubled single quotes
}
27 changes: 23 additions & 4 deletions pyrefly/lib/state/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ use ruff_python_ast::Expr;
use ruff_python_ast::ExprAttribute;
use ruff_python_ast::ExprCall;
use ruff_python_ast::ExprContext;
use ruff_python_parser::parse_module;
use ruff_python_parser::TokenKind;
use ruff_python_parser::ParseErrorType;
use ruff_python_parser::LexicalErrorType;
use ruff_python_ast::ExprName;
use ruff_python_ast::Identifier;
use ruff_python_ast::Keyword;
Expand Down Expand Up @@ -71,6 +75,7 @@ use crate::state::require::Require;
use crate::state::state::CancellableTransaction;
use crate::state::state::Transaction;
use crate::types::callable::Param;
use crate::types::literal::Lit;
use crate::types::module::ModuleType;
use crate::types::types::Type;

Expand Down Expand Up @@ -2352,7 +2357,7 @@ impl<'a> Transaction<'a> {
))
}

fn add_literal_completions(
fn add_literal_completions(
&self,
handle: &Handle,
position: TextSize,
Expand All @@ -2370,20 +2375,34 @@ impl<'a> Transaction<'a> {
}
}

fn add_literal_completions_from_type(param_type: &Type, completions: &mut Vec<CompletionItem>) {
fn add_literal_completions_from_type(
param_type: &Type,
completions: &mut Vec<CompletionItem>,
in_string: bool,
) {
match param_type {
Type::Literal(lit) => {
let label = lit.to_string_escaped(true);
let insert_text = if in_string {
match lit {
Lit::Str(s) => Some(s.to_string()),
_ => None,
}
} else {
None
};
completions.push(CompletionItem {
// TODO: Pass the flag correctly for whether literal string is single quoted or double quoted
label: lit.to_string_escaped(true),
label,
insert_text,
kind: Some(CompletionItemKind::VALUE),
detail: Some(format!("{param_type}")),
..Default::default()
});
}
Type::Union(types) => {
for union_type in types {
Self::add_literal_completions_from_type(union_type, completions);
Self::add_literal_completions_from_type(union_type, completions, in_string);
}
}
_ => {}
Expand Down
33 changes: 13 additions & 20 deletions pyrefly/lib/test/lsp/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,8 @@ foo("
4 | foo("
^
Completion Results:
- (Value) 'a\nb': Literal['a\nb']
- (Value) 'a\nb': Literal['a\nb'] inserting `a
b`
- (Variable) x=: Literal['a\nb']"#
.trim(),
report.trim(),
Expand Down Expand Up @@ -1177,8 +1178,8 @@ foo('
4 | foo('
^
Completion Results:
- (Value) 'bar': Literal['bar']
- (Value) 'foo': Literal['foo']
- (Value) 'bar': Literal['bar'] inserting `bar`
- (Value) 'foo': Literal['foo'] inserting `foo`
- (Variable) x=: Literal['bar', 'foo']
"#
.trim(),
Expand Down Expand Up @@ -1263,30 +1264,22 @@ Completion Results:
);
}

// todo(kylei): provide editttext to remove the quotes
#[test]
fn completion_literal_do_not_duplicate_quotes() {
let code = r#"
from typing import Literal, Union
class Foo: ...
def foo(x: Union[Union[Literal['foo']] | Literal[1] | Foo]): ...
foo(''
from typing import Literal
def foo(fruit: Literal["apple", "pear"]) -> None: ...
foo('
# ^
"#;
let report =
get_batched_lsp_operations_report_allow_error(&[("main", code)], get_default_test_report());
assert_eq!(
r#"
# main.py
5 | foo(''
^
Completion Results:
- (Value) 'foo': Literal['foo']
- (Value) 1: Literal[1]
"#
.trim(),
report.trim(),
);

// We expect the completion to NOT insert extra quotes if we are already in a quote.
// Currently it likely inserts quotes.
println!("{}", report);
assert!(report.contains("inserting `apple`"), "Should insert unquoted apple");
assert!(report.contains("inserting `pear`"), "Should insert unquoted pear");
}

// todo(kylei): completion on known dict values
Expand Down
1 change: 1 addition & 0 deletions pyrefly/lib/test/lsp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

mod code_actions;
mod completion;

mod declaration;
mod definition;
mod diagnostic;
Expand Down