Форматиране на импорти

Предадени решения

Краен срок:
03.12.2024 18:00
Точки:
20

Срокът за предаване на решения е отминал

use solution::*;
#[test]
fn test_flat_empty() {
let imports = &[];
assert_eq!(format_flat(imports, Order::Original), Vec::<String>::new());
assert_eq!(format_flat(imports, Order::Sorted), Vec::<String>::new());
}
#[test]
fn test_flat_original() {
let imports = &[
Import(&["my_crate", "c", "C1"]),
Import(&["my_crate", "b"]),
Import(&["my_crate", "x", "y", "z", "W1"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "c", "C2"]),
];
assert_eq!(
format_flat(imports, Order::Original),
vec![
"my_crate::c::C1",
"my_crate::b",
"my_crate::x::y::z::W1",
"my_crate::a",
"my_crate::c::C2",
]
);
}
#[test]
fn test_flat_original_duplicates() {
let imports = &[
Import(&["std", "string", "String"]),
Import(&["std", "iter", "once"]),
Import(&["std", "iter"]),
Import(&["std", "iter"]),
Import(&["std", "iter", "repeat"]),
Import(&["std", "string", "String"]),
];
assert_eq!(
format_flat(imports, Order::Original),
vec![
"std::string::String",
"std::iter::once",
"std::iter",
"std::iter::repeat",
]
);
}
#[test]
fn test_flat_sorted() {
let imports = &[
Import(&["my_crate", "c", "C1"]),
Import(&["my_crate", "b"]),
Import(&["my_crate", "x", "y", "z", "W1"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "c", "C2"]),
];
assert_eq!(
format_flat(imports, Order::Sorted),
vec![
"my_crate::a",
"my_crate::b",
"my_crate::c::C1",
"my_crate::c::C2",
"my_crate::x::y::z::W1",
]
);
}
#[test]
fn test_flat_sorted_duplicates() {
let imports = &[
Import(&["std", "string", "String"]),
Import(&["std", "iter", "once"]),
Import(&["std", "iter"]),
Import(&["std", "iter"]),
Import(&["std", "iter", "repeat"]),
Import(&["std", "string", "String"]),
];
assert_eq!(
format_flat(imports, Order::Sorted),
vec![
"std::iter",
"std::iter::once",
"std::iter::repeat",
"std::string::String",
]
);
}
#[test]
fn test_flat_multi_crate() {
let imports = &[
Import(&["std", "string", "String"]),
Import(&["foo", "string", "String"]),
Import(&["bar", "string", "String"]),
];
assert_eq!(
format_flat(imports, Order::Original),
vec!["std::string::String", "foo::string::String", "bar::string::String",]
);
assert_eq!(
format_flat(imports, Order::Sorted),
vec!["bar::string::String", "foo::string::String", "std::string::String",]
);
}
#[test]
fn test_nested_empty() {
let imports = &[];
assert_eq!(format_nested(imports, Order::Original), Vec::<String>::new());
assert_eq!(format_nested(imports, Order::Sorted), Vec::<String>::new());
}
#[test]
fn test_nested_only_crate() {
let imports = &[
Import(&["my_crate"]),
];
assert_eq!(format_nested(imports, Order::Original), vec!["my_crate\n"]);
assert_eq!(format_nested(imports, Order::Sorted), vec!["my_crate\n"]);
}
#[test]
fn test_nested_basic() {
let imports = &[Import(&["std", "a"])];
assert_eq!(format_nested(imports, Order::Original), vec!["std::{\n a,\n}\n"]);
assert_eq!(format_nested(imports, Order::Sorted), vec!["std::{\n a,\n}\n"]);
}
#[test]
fn test_nested_deep() {
let imports = &[Import(&["std", "a", "b", "c", "d"])];
let expected = vec![concat!(
"std::{\n",
" a::{\n",
" b::{\n",
" c::{\n",
" d,\n",
" },\n",
" },\n",
" },\n",
"}\n",
)];
assert_eq!(format_nested(imports, Order::Original), expected);
assert_eq!(format_nested(imports, Order::Sorted), expected);
}
#[test]
fn test_nested_original() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
];
assert_eq!(
format_nested(imports, Order::Original),
vec![concat!(
"my_crate::{\n",
" c,\n",
" b::{\n",
" B2,\n",
" B1,\n",
" },\n",
" a,\n",
"}\n",
)]
)
}
#[test]
fn test_nested_original_2() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a", "inner", "I1"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "a", "A1"]),
];
assert_eq!(
format_nested(imports, Order::Original),
vec![concat!(
"my_crate::{\n",
" c,\n",
" b::{\n",
" B2,\n",
" B1,\n",
" },\n",
" a::{\n",
" inner::{\n",
" I1,\n",
" },\n",
" A1,\n",
" },\n",
"}\n",
)]
)
}
#[test]
fn test_nested_sorted() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
];
assert_eq!(
format_nested(imports, Order::Sorted),
vec![concat!(
"my_crate::{\n",
" a,\n",
" b::{\n",
" B1,\n",
" B2,\n",
" },\n",
" c,\n",
"}\n",
)]
)
}
#[test]
fn test_nested_sorted_2() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a", "inner", "I1"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "a", "A1"]),
];
assert_eq!(
format_nested(imports, Order::Sorted),
vec![concat!(
"my_crate::{\n",
" a::{\n",
" A1,\n",
" inner::{\n",
" I1,\n",
" },\n",
" },\n",
" b::{\n",
" B1,\n",
" B2,\n",
" },\n",
" c,\n",
"}\n",
)]
)
}
#[test]
fn test_nested_original_duplicates() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "c"]),
];
assert_eq!(
format_nested(imports, Order::Original),
vec![concat!(
"my_crate::{\n",
" c,\n",
" b::{\n",
" B2,\n",
" B1,\n",
" },\n",
" a,\n",
"}\n",
)]
)
}
#[test]
fn test_nested_sorted_duplicates() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "c"]),
];
assert_eq!(
format_nested(imports, Order::Sorted),
vec![concat!(
"my_crate::{\n",
" a,\n",
" b::{\n",
" B1,\n",
" B2,\n",
" },\n",
" c,\n",
"}\n",
)]
)
}
#[test]
fn test_nested_original_self() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b"]),
];
assert_eq!(
format_nested(imports, Order::Original),
vec![concat!(
"my_crate::{\n",
" c,\n",
" b::{\n",
" self,\n",
" B2,\n",
" B1,\n",
" },\n",
" a,\n",
"}\n",
)]
)
}
#[test]
fn test_nested_sorted_self() {
let imports = &[
Import(&["my_crate", "c"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b"]),
];
assert_eq!(
format_nested(imports, Order::Sorted),
vec![concat!(
"my_crate::{\n",
" a,\n",
" b::{\n",
" self,\n",
" B1,\n",
" B2,\n",
" },\n",
" c,\n",
"}\n",
)]
)
}
#[test]
#[rustfmt::skip]
fn test_nested_original_multi_crate() {
let imports = &[
Import(&["crate", "b"]),
Import(&["std", "string", "String"]),
Import(&["crate", "a"]),
];
assert_eq!(
format_nested(imports, Order::Original),
vec![
concat!(
"crate::{\n",
" b,\n",
" a,\n",
"}\n",
),
concat!(
"std::{\n",
" string::{\n",
" String,\n",
" },\n",
"}\n",
),
]
)
}
#[test]
#[rustfmt::skip]
fn test_nested_sorted_multi_crate() {
let imports = &[
Import(&["crate", "b"]),
Import(&["std", "string", "String"]),
Import(&["crate", "a"]),
];
assert_eq!(
format_nested(imports, Order::Sorted),
vec![
concat!(
"crate::{\n",
" a,\n",
" b,\n",
"}\n",
),
concat!(
"std::{\n",
" string::{\n",
" String,\n",
" },\n",
"}\n",
),
]
)
}

Import-ите в Rust могат да се напишат по няколко различни начина, в зависимост от продпочитанията на програмиста:

// по един импорт на ред
use std::iter;
use std::iter::once;
use std::iter::repeat;

// групирани по модули
use std::collections::hash_map::{Entry, HashMap};
use std::vec::{IntoIter, Vec};

// групирани в едно `use` твърдение
use std::sync::{
    Arc,
    mpsc::{
        Sender,
        Receiver,
    },
};

Целта на това задание е да напишете програма, която форматира списък от импорти в два различни стила.
Програмата трябва да съдържа следното (можете да добавяте произволни derive-ове и методи на Import и Order, ако са ви необходими):

pub struct Import<'a>(pub &'a [&'a str]);

pub enum Order {
    Original,
    Sorted,
}

pub fn format_flat(imports: &[Import], order: Order) -> Vec<String> {
    todo!()
}

pub fn format_nested(imports: &[Import], order: Order) -> Vec<String> {
    todo!()
}

Импортите ще ви се подават предварително разпарсени и разделени на части. Например std::string::String ще се подаде като Import(&["std", "string", "String"]).
Всеки Import ще бъде валиден и ще съдържа абсолютен път до някакъв item, т.е. задължително ще започва с име на външен пакет (като "std") или с ключовата дума "crate". Няма да има импорти, които завършват със "self".

format_flat

Функцията връща импортите форматирани по един на ред. Всеки ред е един елемент от резултата. Параметърът order определя как трябва да са подредени импортите. Ако е Original, трябва се върнат в оригиналния им ред. Ако е Sorted трябва да се върнат сортирани лексикографски. И в двата случая дубликатите трябва да се премахнат. Резултатът трябва да изглежда така:

vec![
    String::from("my_crate::a"),
    String::from("my_crate::b::B1"),
    String::from("my_crate::b::B2"),
]

format_nested

Функцията връща импортите групирани в едно use твърдение за всеки crate (без ключовата дума use и символа ;).
Всеки елемент от резултата трябва да изглежда така:

my_crate::{
    a,
    b::{
        B1,
        B2,
    },
    c,
}
  • резултатът е вектор, който съдържа по един елемент за всеки crate сред подадените импорти. Всеки елемент на вектора е многоредов низ, като този, показан по-горе;
  • форматирането трябва да отговаря точно на показания пример. Всяко ниво на идентация е по 4 интервала;
  • за всеки модул се отваря ново ниво на вложеност, дори и да има само едно име под този модул:

      my_crate::{
          a::{
              b,
          },
      }
    
  • ако е подаден импорт за модул (std::b), както и импорти за имена под този модул (std::b::B1), импорта на самия модул трябва да се преобразува да използва self. self трябва да се добави най-отгоре във вложената група, преди останалите елементи и не се влияе от параметъра order:

      std::{
          b::{
              self,
              B1,
          }
      }
    
  • ако са подадени импорти за няколко различни crate-а, резултатът трябва да съдържа по един низ за всеки crate:

      vec![
          String::from("std::{\n    a,\n}\n"),
          String::from("foo::{\n    b,\n}\n"),
      ]
    
  • дубликатите трябва да се премахнат.

Параметърът order определя в какъв ред трябва да са подредени импортите. Ако е Original, първо трябва да се напишат модулите и item-ите, които се срещат по-рано във входа. Следващи срещания на същия модул трябва да се добавят в същата вложена група:

imports = &[
    Import(&["foo", "b", "B2"]),
    Import(&["foo", "a", "A1"]),
    Import(&["foo", "b", "B1"]),
]

// =>

foo::{
    b::{
        B2,
        B1,
    },
    a::{
        A1,
    },
}

Ако order е Sorted, импортите трябва да са сортирани в лексикографски ред:

imports = &[
    Import(&["foo", "b", "B2"]),
    Import(&["foo", "a", "A1"]),
    Import(&["foo", "b", "B1"]),
]

// =>

foo::{
    a::{
        A1,
    },
    b::{
        B1,
        B2,
    },
}

Подсказки

Следното не е по никакъв начин задължително, но ако се чудите как да подходите към задачата, ето ви един съвет:

  • Резултатът от format_nested има дървовидна форма, затова ще е най-удобно, ако импортите се запазят в дърво, след което това дърво се обходи. Нещо от рода на struct Tree { root: Node }; struct Node { value: String, children: Контейнер<Node> } ще свърши работа. Разбира се, в единия случай децата ни трябват в реда на въвеждане, а в другия - сортирани лексикографски. Има много начини това да се постигне.
    Не се притеснявайте да копирате и сортирате данните колкото пъти ви трябва - не оценяваме бързината на решението.

Задължително прочетете (или си припомнете): Указания за предаване на домашни

Погрижете се решението ви да се компилира с базовия тест:

use solution::*;
#[test]
fn test_basic() {
let imports = &[
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "c"]),
];
assert_eq!(
format_flat(imports, Order::Sorted),
&[
"my_crate::a",
"my_crate::b::B1",
"my_crate::b::B2",
"my_crate::c",
]
);
assert_eq!(
format_nested(imports, Order::Sorted),
&[
concat!(
"my_crate::{\n",
" a,\n",
" b::{\n",
" B1,\n",
" B2,\n",
" },\n",
" c,\n",
"}\n",
)
]
);
}