Skip to content

Commit c4d49cd

Browse files
committed
Easier range checks, and target markers
1 parent 4e4938c commit c4d49cd

5 files changed

Lines changed: 330 additions & 399 deletions

File tree

tooling/lsp/src/requests/document_symbol.rs

Lines changed: 78 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ mod document_symbol_tests {
518518

519519
use super::*;
520520
use async_lsp::lsp_types::{
521-
PartialResultParams, Range, SymbolKind, TextDocumentIdentifier, WorkDoneProgressParams,
521+
PartialResultParams, SymbolKind, TextDocumentIdentifier, WorkDoneProgressParams,
522522
};
523523
use tokio::test;
524524

@@ -554,28 +554,16 @@ mod document_symbol_tests {
554554
"#;
555555
let symbols = get_document_symbols(src).await;
556556

557-
assert_eq!(
558-
symbols,
559-
vec![
560-
#[allow(deprecated)]
561-
DocumentSymbol {
562-
name: "foo".to_string(),
563-
detail: Some("fn foo(_x: i32)".to_string()),
564-
kind: SymbolKind::FUNCTION,
565-
tags: None,
566-
deprecated: None,
567-
range: Range {
568-
start: Position { line: 0, character: 0 },
569-
end: Position { line: 2, character: 1 },
570-
},
571-
selection_range: Range {
572-
start: Position { line: 0, character: 3 },
573-
end: Position { line: 0, character: 6 },
574-
},
575-
children: None,
576-
},
577-
]
578-
);
557+
assert_eq!(symbols.len(), 1);
558+
let symbol = &symbols[0];
559+
assert_eq!(symbol.name, "foo");
560+
assert_eq!(symbol.detail.as_deref(), Some("fn foo(_x: i32)"));
561+
assert_eq!(symbol.kind, SymbolKind::FUNCTION);
562+
assert!(symbol.children.is_none());
563+
// `range` covers the whole function (signature + body).
564+
assert_eq!(test_utils::text_at(src, symbol.range), "fn foo(_x: i32) {\n let _ = 1;\n}");
565+
// `selection_range` covers just the function name.
566+
assert_eq!(test_utils::text_at(src, symbol.selection_range), "foo");
579567
}
580568

581569
#[test]
@@ -586,46 +574,23 @@ mod document_symbol_tests {
586574
"#;
587575
let symbols = get_document_symbols(src).await;
588576

577+
assert_eq!(symbols.len(), 1);
578+
let symbol = &symbols[0];
579+
assert_eq!(symbol.name, "SomeStruct");
580+
assert_eq!(symbol.kind, SymbolKind::STRUCT);
589581
assert_eq!(
590-
symbols,
591-
vec![
592-
#[allow(deprecated)]
593-
DocumentSymbol {
594-
name: "SomeStruct".to_string(),
595-
detail: None,
596-
kind: SymbolKind::STRUCT,
597-
tags: None,
598-
deprecated: None,
599-
range: Range {
600-
start: Position { line: 0, character: 0 },
601-
end: Position { line: 2, character: 1 },
602-
},
603-
selection_range: Range {
604-
start: Position { line: 0, character: 7 },
605-
end: Position { line: 0, character: 17 },
606-
},
607-
children: Some(vec![
608-
#[allow(deprecated)]
609-
DocumentSymbol {
610-
name: "field".to_string(),
611-
detail: None,
612-
kind: SymbolKind::FIELD,
613-
tags: None,
614-
deprecated: None,
615-
range: Range {
616-
start: Position { line: 1, character: 4 },
617-
end: Position { line: 1, character: 14 },
618-
},
619-
selection_range: Range {
620-
start: Position { line: 1, character: 4 },
621-
end: Position { line: 1, character: 9 },
622-
},
623-
children: None,
624-
},
625-
],),
626-
},
627-
]
582+
test_utils::text_at(src, symbol.range),
583+
"struct SomeStruct {\n field: i32,\n}"
628584
);
585+
assert_eq!(test_utils::text_at(src, symbol.selection_range), "SomeStruct");
586+
587+
let children = symbol.children.as_ref().expect("Expected children");
588+
assert_eq!(children.len(), 1);
589+
let field = &children[0];
590+
assert_eq!(field.name, "field");
591+
assert_eq!(field.kind, SymbolKind::FIELD);
592+
assert_eq!(test_utils::text_at(src, field.range), "field: i32");
593+
assert_eq!(test_utils::text_at(src, field.selection_range), "field");
629594
}
630595

631596
#[test]
@@ -644,19 +609,10 @@ impl SomeStruct {
644609
assert_eq!(impl_symbol.name, "SomeStruct");
645610
assert_eq!(impl_symbol.kind, SymbolKind::NAMESPACE);
646611
assert_eq!(
647-
impl_symbol.range,
648-
Range {
649-
start: Position { line: 2, character: 0 },
650-
end: Position { line: 6, character: 1 },
651-
}
652-
);
653-
assert_eq!(
654-
impl_symbol.selection_range,
655-
Range {
656-
start: Position { line: 2, character: 5 },
657-
end: Position { line: 2, character: 15 },
658-
}
612+
test_utils::text_at(src, impl_symbol.range),
613+
"impl SomeStruct {\n fn new() -> SomeStruct {\n SomeStruct {}\n }\n}"
659614
);
615+
assert_eq!(test_utils::text_at(src, impl_symbol.selection_range), "SomeStruct");
660616

661617
let children = impl_symbol.children.as_ref().expect("Expected children");
662618
assert_eq!(children.len(), 1);
@@ -665,19 +621,10 @@ impl SomeStruct {
665621
assert_eq!(method.detail.as_deref(), Some("fn new() -> SomeStruct"));
666622
assert_eq!(method.kind, SymbolKind::FUNCTION);
667623
assert_eq!(
668-
method.range,
669-
Range {
670-
start: Position { line: 3, character: 4 },
671-
end: Position { line: 5, character: 5 },
672-
}
673-
);
674-
assert_eq!(
675-
method.selection_range,
676-
Range {
677-
start: Position { line: 3, character: 7 },
678-
end: Position { line: 3, character: 10 },
679-
}
624+
test_utils::text_at(src, method.range),
625+
"fn new() -> SomeStruct {\n SomeStruct {}\n }"
680626
);
627+
assert_eq!(test_utils::text_at(src, method.selection_range), "new");
681628
}
682629

683630
#[test]
@@ -688,46 +635,24 @@ impl SomeStruct {
688635
"#;
689636
let symbols = get_document_symbols(src).await;
690637

638+
assert_eq!(symbols.len(), 1);
639+
let trait_symbol = &symbols[0];
640+
assert_eq!(trait_symbol.name, "SomeTrait");
641+
assert_eq!(trait_symbol.kind, SymbolKind::INTERFACE);
691642
assert_eq!(
692-
symbols,
693-
vec![
694-
#[allow(deprecated)]
695-
DocumentSymbol {
696-
name: "SomeTrait".to_string(),
697-
detail: None,
698-
kind: SymbolKind::INTERFACE,
699-
tags: None,
700-
deprecated: None,
701-
range: Range {
702-
start: Position { line: 0, character: 0 },
703-
end: Position { line: 2, character: 1 },
704-
},
705-
selection_range: Range {
706-
start: Position { line: 0, character: 6 },
707-
end: Position { line: 0, character: 15 },
708-
},
709-
children: Some(vec![
710-
#[allow(deprecated)]
711-
DocumentSymbol {
712-
name: "some_method".to_string(),
713-
detail: None,
714-
kind: SymbolKind::METHOD,
715-
tags: None,
716-
deprecated: None,
717-
range: Range {
718-
start: Position { line: 1, character: 7 },
719-
end: Position { line: 1, character: 25 },
720-
},
721-
selection_range: Range {
722-
start: Position { line: 1, character: 7 },
723-
end: Position { line: 1, character: 18 },
724-
},
725-
children: None,
726-
},
727-
],),
728-
},
729-
]
643+
test_utils::text_at(src, trait_symbol.range),
644+
"trait SomeTrait<U> {\n fn some_method(x: U);\n}"
730645
);
646+
assert_eq!(test_utils::text_at(src, trait_symbol.selection_range), "SomeTrait");
647+
648+
let children = trait_symbol.children.as_ref().expect("Expected children");
649+
assert_eq!(children.len(), 1);
650+
let method = &children[0];
651+
assert_eq!(method.name, "some_method");
652+
assert_eq!(method.kind, SymbolKind::METHOD);
653+
// For a trait method declaration, `range` starts at the method name (not `fn`).
654+
assert_eq!(test_utils::text_at(src, method.range), "some_method(x: U);");
655+
assert_eq!(test_utils::text_at(src, method.selection_range), "some_method");
731656
}
732657

733658
#[test]
@@ -751,19 +676,11 @@ impl SomeTrait<i32> for SomeStruct {
751676
assert_eq!(impl_symbol.name, "impl SomeTrait<i32> for SomeStruct");
752677
assert_eq!(impl_symbol.kind, SymbolKind::NAMESPACE);
753678
assert_eq!(
754-
impl_symbol.range,
755-
Range {
756-
start: Position { line: 6, character: 0 },
757-
end: Position { line: 9, character: 1 },
758-
}
759-
);
760-
assert_eq!(
761-
impl_symbol.selection_range,
762-
Range {
763-
start: Position { line: 6, character: 5 },
764-
end: Position { line: 6, character: 14 },
765-
}
679+
test_utils::text_at(src, impl_symbol.range),
680+
"impl SomeTrait<i32> for SomeStruct {\n fn some_method(_x: i32) {\n }\n}"
766681
);
682+
// For a trait impl, `selection_range` points at the trait name (not the target type).
683+
assert_eq!(test_utils::text_at(src, impl_symbol.selection_range), "SomeTrait");
767684

768685
let children = impl_symbol.children.as_ref().expect("Expected children");
769686
assert_eq!(children.len(), 1);
@@ -781,75 +698,37 @@ impl SomeTrait<i32> for SomeStruct {
781698
"#;
782699
let symbols = get_document_symbols(src).await;
783700

701+
assert_eq!(symbols.len(), 1);
702+
let module = &symbols[0];
703+
assert_eq!(module.name, "submodule");
704+
assert_eq!(module.kind, SymbolKind::MODULE);
784705
assert_eq!(
785-
symbols,
786-
vec![
787-
#[allow(deprecated)]
788-
DocumentSymbol {
789-
name: "submodule".to_string(),
790-
detail: None,
791-
kind: SymbolKind::MODULE,
792-
tags: None,
793-
deprecated: None,
794-
range: Range {
795-
start: Position { line: 0, character: 0 },
796-
end: Position { line: 2, character: 1 },
797-
},
798-
selection_range: Range {
799-
start: Position { line: 0, character: 4 },
800-
end: Position { line: 0, character: 13 },
801-
},
802-
children: Some(vec![
803-
#[allow(deprecated)]
804-
DocumentSymbol {
805-
name: "SOME_GLOBAL".to_string(),
806-
detail: None,
807-
kind: SymbolKind::CONSTANT,
808-
tags: None,
809-
deprecated: None,
810-
range: Range {
811-
start: Position { line: 1, character: 4 },
812-
end: Position { line: 1, character: 27 },
813-
},
814-
selection_range: Range {
815-
start: Position { line: 1, character: 11 },
816-
end: Position { line: 1, character: 22 },
817-
},
818-
children: None,
819-
},
820-
]),
821-
},
822-
]
706+
test_utils::text_at(src, module.range),
707+
"mod submodule {\n global SOME_GLOBAL = 1;\n}"
823708
);
709+
assert_eq!(test_utils::text_at(src, module.selection_range), "submodule");
710+
711+
let children = module.children.as_ref().expect("Expected children");
712+
assert_eq!(children.len(), 1);
713+
let global = &children[0];
714+
assert_eq!(global.name, "SOME_GLOBAL");
715+
assert_eq!(global.kind, SymbolKind::CONSTANT);
716+
assert_eq!(test_utils::text_at(src, global.range), "global SOME_GLOBAL = 1;");
717+
assert_eq!(test_utils::text_at(src, global.selection_range), "SOME_GLOBAL");
824718
}
825719

826720
#[test]
827721
async fn test_document_symbol_for_primitive_impl() {
828722
let src = "impl i32 {}\n";
829723
let symbols = get_document_symbols(src).await;
830724

831-
assert_eq!(
832-
symbols,
833-
vec![
834-
#[allow(deprecated)]
835-
DocumentSymbol {
836-
name: "i32".to_string(),
837-
detail: None,
838-
kind: SymbolKind::NAMESPACE,
839-
tags: None,
840-
deprecated: None,
841-
range: Range {
842-
start: Position { line: 0, character: 0 },
843-
end: Position { line: 0, character: 11 },
844-
},
845-
selection_range: Range {
846-
start: Position { line: 0, character: 5 },
847-
end: Position { line: 0, character: 8 },
848-
},
849-
children: Some(Vec::new()),
850-
},
851-
]
852-
);
725+
assert_eq!(symbols.len(), 1);
726+
let symbol = &symbols[0];
727+
assert_eq!(symbol.name, "i32");
728+
assert_eq!(symbol.kind, SymbolKind::NAMESPACE);
729+
assert_eq!(test_utils::text_at(src, symbol.range), "impl i32 {}");
730+
assert_eq!(test_utils::text_at(src, symbol.selection_range), "i32");
731+
assert_eq!(symbol.children.as_deref(), Some(&[][..]));
853732
}
854733

855734
#[test]
@@ -858,19 +737,9 @@ impl SomeTrait<i32> for SomeStruct {
858737
let mut symbols = get_document_symbols(src).await;
859738
assert_eq!(symbols.len(), 1);
860739
let symbol = symbols.remove(0);
861-
assert_eq!(
862-
symbol.range,
863-
Range {
864-
start: Position { line: 0, character: 0 },
865-
end: Position { line: 1, character: 0 },
866-
}
867-
);
868-
assert_eq!(
869-
symbol.selection_range,
870-
Range {
871-
start: Position { line: 0, character: 3 },
872-
end: Position { line: 0, character: 7 },
873-
}
874-
);
740+
// Parse-recovery: the symbol's range extends from `fn` to the end of the only line
741+
// (the function never gets a proper close), and its selection_range is the name.
742+
assert_eq!(test_utils::text_at(src, symbol.range), "fn main(\n");
743+
assert_eq!(test_utils::text_at(src, symbol.selection_range), "main");
875744
}
876745
}

0 commit comments

Comments
 (0)