Merge #4839
4839: `Go to Type Definition` hover action. r=matklad a=vsrs  This implementation supports things like `dyn Trait<SomeType>`, `-> impl Trait`, etc. Co-authored-by: vsrs <vit@conrlab.com>
This commit is contained in:
@@ -26,8 +26,8 @@ use hir_ty::{
|
|||||||
autoderef,
|
autoderef,
|
||||||
display::{HirDisplayError, HirFormatter},
|
display::{HirDisplayError, HirFormatter},
|
||||||
expr::ExprValidator,
|
expr::ExprValidator,
|
||||||
method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
|
method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
|
||||||
TyDefId, TypeCtor,
|
TraitEnvironment, Ty, TyDefId, TypeCtor,
|
||||||
};
|
};
|
||||||
use ra_db::{CrateId, CrateName, Edition, FileId};
|
use ra_db::{CrateId, CrateName, Edition, FileId};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
@@ -186,6 +186,22 @@ impl ModuleDef {
|
|||||||
|
|
||||||
module.visibility_of(db, self)
|
module.visibility_of(db, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
||||||
|
match self {
|
||||||
|
ModuleDef::Adt(it) => Some(it.name(db)),
|
||||||
|
ModuleDef::Trait(it) => Some(it.name(db)),
|
||||||
|
ModuleDef::Function(it) => Some(it.name(db)),
|
||||||
|
ModuleDef::EnumVariant(it) => Some(it.name(db)),
|
||||||
|
ModuleDef::TypeAlias(it) => Some(it.name(db)),
|
||||||
|
|
||||||
|
ModuleDef::Module(it) => it.name(db),
|
||||||
|
ModuleDef::Const(it) => it.name(db),
|
||||||
|
ModuleDef::Static(it) => it.name(db),
|
||||||
|
|
||||||
|
ModuleDef::BuiltinType(it) => Some(it.as_name()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use hir_def::{
|
pub use hir_def::{
|
||||||
@@ -1359,6 +1375,27 @@ impl Type {
|
|||||||
Some(adt.into())
|
Some(adt.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_dyn_trait(&self) -> Option<Trait> {
|
||||||
|
self.ty.value.dyn_trait().map(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
|
||||||
|
self.ty.value.impl_trait_bounds(db).map(|it| {
|
||||||
|
it.into_iter()
|
||||||
|
.filter_map(|pred| match pred {
|
||||||
|
hir_ty::GenericPredicate::Implemented(trait_ref) => {
|
||||||
|
Some(Trait::from(trait_ref.trait_))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
|
||||||
|
self.ty.value.associated_type_parent_trait(db).map(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: provide required accessors such that it becomes implementable from outside.
|
// FIXME: provide required accessors such that it becomes implementable from outside.
|
||||||
pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
|
pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
|
||||||
match (&self.ty.value, &other.ty.value) {
|
match (&self.ty.value, &other.ty.value) {
|
||||||
@@ -1380,6 +1417,80 @@ impl Type {
|
|||||||
ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
|
ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
|
||||||
|
// TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
|
||||||
|
// We need a different order here.
|
||||||
|
|
||||||
|
fn walk_substs(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
type_: &Type,
|
||||||
|
substs: &Substs,
|
||||||
|
cb: &mut impl FnMut(Type),
|
||||||
|
) {
|
||||||
|
for ty in substs.iter() {
|
||||||
|
walk_type(db, &type_.derived(ty.clone()), cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_bounds(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
type_: &Type,
|
||||||
|
bounds: &[GenericPredicate],
|
||||||
|
cb: &mut impl FnMut(Type),
|
||||||
|
) {
|
||||||
|
for pred in bounds {
|
||||||
|
match pred {
|
||||||
|
GenericPredicate::Implemented(trait_ref) => {
|
||||||
|
cb(type_.clone());
|
||||||
|
walk_substs(db, type_, &trait_ref.substs, cb);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
|
||||||
|
let ty = type_.ty.value.strip_references();
|
||||||
|
match ty {
|
||||||
|
Ty::Apply(ApplicationTy { ctor, parameters }) => {
|
||||||
|
match ctor {
|
||||||
|
TypeCtor::Adt(_) => {
|
||||||
|
cb(type_.derived(ty.clone()));
|
||||||
|
}
|
||||||
|
TypeCtor::AssociatedType(_) => {
|
||||||
|
if let Some(_) = ty.associated_type_parent_trait(db) {
|
||||||
|
cb(type_.derived(ty.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
// adt params, tuples, etc...
|
||||||
|
walk_substs(db, type_, parameters, cb);
|
||||||
|
}
|
||||||
|
Ty::Opaque(opaque_ty) => {
|
||||||
|
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
||||||
|
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_substs(db, type_, &opaque_ty.parameters, cb);
|
||||||
|
}
|
||||||
|
Ty::Placeholder(_) => {
|
||||||
|
if let Some(bounds) = ty.impl_trait_bounds(db) {
|
||||||
|
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ty::Dyn(bounds) => {
|
||||||
|
walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
walk_type(db, self, &mut cb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HirDisplay for Type {
|
impl HirDisplay for Type {
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ pub use lower::{
|
|||||||
pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
|
pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
|
||||||
|
|
||||||
pub use chalk_ir::{BoundVar, DebruijnIndex};
|
pub use chalk_ir::{BoundVar, DebruijnIndex};
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
/// A type constructor or type name: this might be something like the primitive
|
/// A type constructor or type name: this might be something like the primitive
|
||||||
/// type `bool`, a struct like `Vec`, or things like function pointers or
|
/// type `bool`, a struct like `Vec`, or things like function pointers or
|
||||||
@@ -815,6 +816,11 @@ impl Ty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If this is a `dyn Trait`, returns that trait.
|
||||||
|
pub fn dyn_trait(&self) -> Option<TraitId> {
|
||||||
|
self.dyn_trait_ref().map(|it| it.trait_)
|
||||||
|
}
|
||||||
|
|
||||||
fn builtin_deref(&self) -> Option<Ty> {
|
fn builtin_deref(&self) -> Option<Ty> {
|
||||||
match self {
|
match self {
|
||||||
Ty::Apply(a_ty) => match a_ty.ctor {
|
Ty::Apply(a_ty) => match a_ty.ctor {
|
||||||
@@ -867,13 +873,56 @@ impl Ty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If this is a `dyn Trait`, returns that trait.
|
pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
|
||||||
pub fn dyn_trait(&self) -> Option<TraitId> {
|
|
||||||
match self {
|
match self {
|
||||||
Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
|
Ty::Opaque(opaque_ty) => {
|
||||||
GenericPredicate::Implemented(tr) => Some(tr.trait_),
|
let predicates = match opaque_ty.opaque_ty_id {
|
||||||
|
OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
|
||||||
|
db.return_type_impl_traits(func).map(|it| {
|
||||||
|
let data = (*it)
|
||||||
|
.as_ref()
|
||||||
|
.map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
|
||||||
|
data.clone().subst(&opaque_ty.parameters)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
predicates.map(|it| it.value)
|
||||||
|
}
|
||||||
|
Ty::Placeholder(id) => {
|
||||||
|
let generic_params = db.generic_params(id.parent);
|
||||||
|
let param_data = &generic_params.types[id.local_id];
|
||||||
|
match param_data.provenance {
|
||||||
|
hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
|
||||||
|
let predicates = db
|
||||||
|
.generic_predicates_for_param(*id)
|
||||||
|
.into_iter()
|
||||||
|
.map(|pred| pred.value.clone())
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
Some(predicates)
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}),
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
|
||||||
|
match self {
|
||||||
|
Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => {
|
||||||
|
match type_alias_id.lookup(db.upcast()).container {
|
||||||
|
AssocContainerId::TraitId(trait_id) => Some(trait_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ty::Projection(projection_ty) => {
|
||||||
|
match projection_ty.associated_ty.lookup(db.upcast()).container {
|
||||||
|
AssocContainerId::TraitId(trait_id) => Some(trait_id),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1057,5 +1106,5 @@ pub struct ReturnTypeImplTraits {
|
|||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub(crate) struct ReturnTypeImplTrait {
|
pub(crate) struct ReturnTypeImplTrait {
|
||||||
pub(crate) bounds: Binders<Vec<GenericPredicate>>,
|
pub bounds: Binders<Vec<GenericPredicate>>,
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,7 @@ pub use crate::{
|
|||||||
display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
|
display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
|
||||||
expand_macro::ExpandedMacro,
|
expand_macro::ExpandedMacro,
|
||||||
folding_ranges::{Fold, FoldKind},
|
folding_ranges::{Fold, FoldKind},
|
||||||
hover::{HoverAction, HoverConfig, HoverResult},
|
hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
|
||||||
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
|
inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
|
||||||
references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
|
references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
|
||||||
runnables::{Runnable, RunnableKind, TestId},
|
runnables::{Runnable, RunnableKind, TestId},
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ impl Config {
|
|||||||
set(value, "/hoverActions/implementations", &mut self.hover.implementations);
|
set(value, "/hoverActions/implementations", &mut self.hover.implementations);
|
||||||
set(value, "/hoverActions/run", &mut self.hover.run);
|
set(value, "/hoverActions/run", &mut self.hover.run);
|
||||||
set(value, "/hoverActions/debug", &mut self.hover.debug);
|
set(value, "/hoverActions/debug", &mut self.hover.debug);
|
||||||
|
set(value, "/hoverActions/gotoTypeDef", &mut self.hover.goto_type_def);
|
||||||
} else {
|
} else {
|
||||||
self.hover = HoverConfig::NO_ACTIONS;
|
self.hover = HoverConfig::NO_ACTIONS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ use lsp_types::{
|
|||||||
TextDocumentIdentifier, Url, WorkspaceEdit,
|
TextDocumentIdentifier, Url, WorkspaceEdit,
|
||||||
};
|
};
|
||||||
use ra_ide::{
|
use ra_ide::{
|
||||||
FileId, FilePosition, FileRange, HoverAction, Query, RangeInfo, Runnable, RunnableKind,
|
FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query,
|
||||||
SearchScope, TextEdit,
|
RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit,
|
||||||
};
|
};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use ra_project_model::TargetKind;
|
use ra_project_model::TargetKind;
|
||||||
@@ -1150,6 +1150,23 @@ fn debug_single_command(runnable: &lsp_ext::Runnable) -> Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn goto_location_command(snap: &GlobalStateSnapshot, nav: &NavigationTarget) -> Option<Command> {
|
||||||
|
let value = if snap.config.client_caps.location_link {
|
||||||
|
let link = to_proto::location_link(snap, None, nav.clone()).ok()?;
|
||||||
|
to_value(link).ok()?
|
||||||
|
} else {
|
||||||
|
let range = FileRange { file_id: nav.file_id(), range: nav.range() };
|
||||||
|
let location = to_proto::location(snap, range).ok()?;
|
||||||
|
to_value(location).ok()?
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(Command {
|
||||||
|
title: nav.name().to_string(),
|
||||||
|
command: "rust-analyzer.gotoLocation".into(),
|
||||||
|
arguments: Some(vec![value]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn to_command_link(command: Command, tooltip: String) -> lsp_ext::CommandLink {
|
fn to_command_link(command: Command, tooltip: String) -> lsp_ext::CommandLink {
|
||||||
lsp_ext::CommandLink { tooltip: Some(tooltip), command }
|
lsp_ext::CommandLink { tooltip: Some(tooltip), command }
|
||||||
}
|
}
|
||||||
@@ -1180,13 +1197,13 @@ fn show_impl_command_link(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_runnable_action(
|
fn runnable_action_links(
|
||||||
snap: &GlobalStateSnapshot,
|
snap: &GlobalStateSnapshot,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
runnable: Runnable,
|
runnable: Runnable,
|
||||||
) -> Option<lsp_ext::CommandLinkGroup> {
|
) -> Option<lsp_ext::CommandLinkGroup> {
|
||||||
let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?;
|
let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?;
|
||||||
if should_skip_target(&runnable, cargo_spec.as_ref()) {
|
if !snap.config.hover.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1208,6 +1225,26 @@ fn to_runnable_action(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn goto_type_action_links(
|
||||||
|
snap: &GlobalStateSnapshot,
|
||||||
|
nav_targets: &[HoverGotoTypeData],
|
||||||
|
) -> Option<lsp_ext::CommandLinkGroup> {
|
||||||
|
if !snap.config.hover.goto_type_def || nav_targets.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(lsp_ext::CommandLinkGroup {
|
||||||
|
title: Some("Go to ".into()),
|
||||||
|
commands: nav_targets
|
||||||
|
.iter()
|
||||||
|
.filter_map(|it| {
|
||||||
|
goto_location_command(snap, &it.nav)
|
||||||
|
.map(|cmd| to_command_link(cmd, it.mod_path.clone()))
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare_hover_actions(
|
fn prepare_hover_actions(
|
||||||
snap: &GlobalStateSnapshot,
|
snap: &GlobalStateSnapshot,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
@@ -1221,7 +1258,8 @@ fn prepare_hover_actions(
|
|||||||
.iter()
|
.iter()
|
||||||
.filter_map(|it| match it {
|
.filter_map(|it| match it {
|
||||||
HoverAction::Implementaion(position) => show_impl_command_link(snap, position),
|
HoverAction::Implementaion(position) => show_impl_command_link(snap, position),
|
||||||
HoverAction::Runnable(r) => to_runnable_action(snap, file_id, r.clone()),
|
HoverAction::Runnable(r) => runnable_action_links(snap, file_id, r.clone()),
|
||||||
|
HoverAction::GoToType(targets) => goto_type_action_links(snap, targets),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -510,6 +510,11 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
|
"rust-analyzer.hoverActions.gotoTypeDef": {
|
||||||
|
"markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
"rust-analyzer.linkedProjects": {
|
"rust-analyzer.linkedProjects": {
|
||||||
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects. \nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format",
|
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects. \nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
|||||||
@@ -353,6 +353,20 @@ export function applyActionGroup(_ctx: Ctx): Cmd {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function gotoLocation(ctx: Ctx): Cmd {
|
||||||
|
return async (locationLink: lc.LocationLink) => {
|
||||||
|
const client = ctx.client;
|
||||||
|
if (client) {
|
||||||
|
const uri = client.protocol2CodeConverter.asUri(locationLink.targetUri);
|
||||||
|
let range = client.protocol2CodeConverter.asRange(locationLink.targetSelectionRange);
|
||||||
|
// collapse the range to a cursor position
|
||||||
|
range = range.with({ end: range.start });
|
||||||
|
|
||||||
|
await vscode.window.showTextDocument(uri, { selection: range });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveCodeAction(ctx: Ctx): Cmd {
|
export function resolveCodeAction(ctx: Ctx): Cmd {
|
||||||
const client = ctx.client;
|
const client = ctx.client;
|
||||||
return async (params: ra.ResolveCodeActionParams) => {
|
return async (params: ra.ResolveCodeActionParams) => {
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export class Config {
|
|||||||
return {
|
return {
|
||||||
engine: this.get<string>("debug.engine"),
|
engine: this.get<string>("debug.engine"),
|
||||||
engineSettings: this.get<object>("debug.engineSettings"),
|
engineSettings: this.get<object>("debug.engineSettings"),
|
||||||
openUpDebugPane: this.get<boolean>("debug.openUpDebugPane"),
|
openDebugPane: this.get<boolean>("debug.openDebugPane"),
|
||||||
sourceFileMap: sourceFileMap
|
sourceFileMap: sourceFileMap
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -135,6 +135,9 @@ export class Config {
|
|||||||
return {
|
return {
|
||||||
enable: this.get<boolean>("hoverActions.enable"),
|
enable: this.get<boolean>("hoverActions.enable"),
|
||||||
implementations: this.get<boolean>("hoverActions.implementations"),
|
implementations: this.get<boolean>("hoverActions.implementations"),
|
||||||
|
run: this.get<boolean>("hoverActions.run"),
|
||||||
|
debug: this.get<boolean>("hoverActions.debug"),
|
||||||
|
gotoTypeDef: this.get<boolean>("hoverActions.gotoTypeDef"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ async function getDebugConfiguration(ctx: Ctx, runnable: ra.Runnable): Promise<v
|
|||||||
}
|
}
|
||||||
|
|
||||||
debugOutput.clear();
|
debugOutput.clear();
|
||||||
if (ctx.config.debug.openUpDebugPane) {
|
if (ctx.config.debug.openDebugPane) {
|
||||||
debugOutput.show(true);
|
debugOutput.show(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand);
|
ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand);
|
||||||
ctx.registerCommand('resolveCodeAction', commands.resolveCodeAction);
|
ctx.registerCommand('resolveCodeAction', commands.resolveCodeAction);
|
||||||
ctx.registerCommand('applyActionGroup', commands.applyActionGroup);
|
ctx.registerCommand('applyActionGroup', commands.applyActionGroup);
|
||||||
|
ctx.registerCommand('gotoLocation', commands.gotoLocation);
|
||||||
|
|
||||||
ctx.pushCleanup(activateTaskProvider(workspaceFolder));
|
ctx.pushCleanup(activateTaskProvider(workspaceFolder));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user