5695: Added completion for unstable features r=matklad a=Fihtangolz

Added xtask for downloading list of unstable features from the unstable book and codegen for it. Also included small changes from linter.

Co-authored-by: Dmitry <mamhigtt@gmail.com>
Co-authored-by: Dmitry Opokin <mamhigtt@gmail.com>
This commit is contained in:
bors[bot] 2020-08-18 16:49:06 +00:00 committed by GitHub
commit f18f9da7d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 8 deletions

View file

@ -1,4 +1,4 @@
//! FIXME: write short doc here
//! Provides set of implementation for hir's objects that allows get back location in file.
use either::Either;
use hir_def::{

View file

@ -18,6 +18,7 @@ mod complete_unqualified_path;
mod complete_postfix;
mod complete_macro_in_item_position;
mod complete_trait_impl;
mod unstable_feature_descriptor;
use ide_db::RootDatabase;
@ -29,6 +30,11 @@ use crate::{
FilePosition,
};
//FIXME: cyclic imports caused by xtask generation, this should be better
use crate::completion::{
complete_attribute::LintCompletion, unstable_feature_descriptor::UNSTABLE_FEATURE_DESCRIPTOR,
};
pub use crate::completion::{
completion_config::CompletionConfig,
completion_item::{CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat},

View file

@ -9,6 +9,7 @@ use syntax::{ast, AstNode, SyntaxKind};
use crate::completion::{
completion_context::CompletionContext,
completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions},
UNSTABLE_FEATURE_DESCRIPTOR,
};
pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
@ -17,12 +18,15 @@ pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
(Some(path), Some(token_tree)) if path.to_string() == "derive" => {
complete_derive(acc, ctx, token_tree)
}
(Some(path), Some(token_tree)) if path.to_string() == "feature" => {
complete_lint(acc, ctx, token_tree, UNSTABLE_FEATURE_DESCRIPTOR)
}
(Some(path), Some(token_tree))
if ["allow", "warn", "deny", "forbid"]
.iter()
.any(|lint_level| lint_level == &path.to_string()) =>
{
complete_lint(acc, ctx, token_tree)
complete_lint(acc, ctx, token_tree, DEFAULT_LINT_COMPLETIONS)
}
(_, Some(_token_tree)) => {}
_ => complete_attribute_start(acc, ctx, attribute),
@ -162,9 +166,14 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input:
}
}
fn complete_lint(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) {
fn complete_lint(
acc: &mut Completions,
ctx: &CompletionContext,
derive_input: ast::TokenTree,
lints_completions: &[LintCompletion],
) {
if let Ok(existing_lints) = parse_comma_sep_input(derive_input) {
for lint_completion in DEFAULT_LINT_COMPLETIONS
for lint_completion in lints_completions
.into_iter()
.filter(|completion| !existing_lints.contains(completion.label))
{
@ -228,7 +237,7 @@ fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> {
result
}
struct DeriveCompletion {
pub(crate) struct DeriveCompletion {
label: &'static str,
dependencies: &'static [&'static str],
}
@ -248,9 +257,9 @@ const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[
DeriveCompletion { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] },
];
struct LintCompletion {
label: &'static str,
description: &'static str,
pub(crate) struct LintCompletion {
pub(crate) label: &'static str,
pub(crate) description: &'static str,
}
#[rustfmt::skip]

File diff suppressed because one or more lines are too long

View file

@ -9,6 +9,7 @@ mod gen_syntax;
mod gen_parser_tests;
mod gen_assists_docs;
mod gen_feature_docs;
mod gen_unstable_future_descriptor;
use std::{
fmt, mem,
@ -26,8 +27,12 @@ pub use self::{
gen_feature_docs::generate_feature_docs,
gen_parser_tests::generate_parser_tests,
gen_syntax::generate_syntax,
gen_unstable_future_descriptor::generate_unstable_future_descriptor,
};
// Directory used by xtask
const STORAGE: &str = ".xtask";
const GRAMMAR_DIR: &str = "crates/parser/src/grammar";
const OK_INLINE_TESTS_DIR: &str = "crates/syntax/test_data/parser/inline/ok";
const ERR_INLINE_TESTS_DIR: &str = "crates/syntax/test_data/parser/inline/err";
@ -39,6 +44,10 @@ const AST_TOKENS: &str = "crates/syntax/src/ast/generated/tokens.rs";
const ASSISTS_DIR: &str = "crates/assists/src/handlers";
const ASSISTS_TESTS: &str = "crates/assists/src/tests/generated.rs";
const REPOSITORY_URL: &str = "https://github.com/rust-lang/rust";
const UNSTABLE_FEATURE: &str = "crates/ide/src/completion/unstable_feature_descriptor.rs";
const REPO_PATH: &str = "src/doc/unstable-book/src";
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Mode {
Overwrite,

View file

@ -0,0 +1,61 @@
//! Generates descriptors structure for unstable feature from Unstable Book
use crate::codegen::{self, project_root, Mode, Result};
use crate::codegen::{reformat, update};
use crate::not_bash::{fs2, pushd, run};
use proc_macro2::TokenStream;
use quote::quote;
use std::path::PathBuf;
use walkdir::WalkDir;
fn generate_descriptor(src_dir: PathBuf) -> Result<TokenStream> {
let files = WalkDir::new(src_dir.join("language-features"))
.into_iter()
.chain(WalkDir::new(src_dir.join("library-features")))
.filter_map(|e| e.ok())
.filter(|entry| {
// Get all `.md ` files
entry.file_type().is_file() && entry.path().extension().unwrap_or_default() == "md"
})
.collect::<Vec<_>>();
let definitions = files
.iter()
.map(|entry| {
let path = entry.path();
let feature_ident =
format!("{}", path.file_stem().unwrap().to_str().unwrap().replace("-", "_"));
let doc = format!("{}", std::fs::read_to_string(path).unwrap());
quote! { LintCompletion { label: #feature_ident, description: #doc } }
})
.collect::<Vec<_>>();
let ts = quote! {
use crate::completion::LintCompletion;
pub(crate) const UNSTABLE_FEATURE_DESCRIPTOR: &[LintCompletion] = &[
#(#definitions),*
];
};
Ok(ts)
}
pub fn generate_unstable_future_descriptor(mode: Mode) -> Result<()> {
let path = project_root().join(codegen::STORAGE);
fs2::create_dir_all(path.clone())?;
let _d = pushd(path.clone());
run!("git init")?;
run!("git remote add -f origin {}", codegen::REPOSITORY_URL)?;
run!("git pull origin master")?;
let src_dir = path.join(codegen::REPO_PATH);
let content = generate_descriptor(src_dir)?.to_string();
let contents = reformat(content)?;
let destination = project_root().join(codegen::UNSTABLE_FEATURE);
update(destination.as_path(), &contents, mode)?;
Ok(())
}

View file

@ -77,6 +77,7 @@ FLAGS:
"codegen" => {
args.finish()?;
codegen::generate_syntax(Mode::Overwrite)?;
codegen::generate_unstable_future_descriptor(Mode::Overwrite)?;
codegen::generate_parser_tests(Mode::Overwrite)?;
codegen::generate_assists_tests(Mode::Overwrite)?;
codegen::generate_assists_docs(Mode::Overwrite)?;

View file

@ -112,6 +112,8 @@ fn check_todo(path: &Path, text: &str) {
// To support generating `todo!()` in assists, we have `expr_todo()` in
// `ast::make`.
"ast/make.rs",
// The documentation in string literals may contain anything for its own purposes
"completion/unstable_feature_descriptor.rs",
];
if need_todo.iter().any(|p| path.ends_with(p)) {
return;