-
Notifications
You must be signed in to change notification settings - Fork 369
Expand file tree
/
Copy pathanalysis_result.rs
More file actions
147 lines (137 loc) · 5.21 KB
/
Copy pathanalysis_result.rs
File metadata and controls
147 lines (137 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is dual-licensed under either the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree or the Apache
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
* of this source tree. You may select, at your option, one of the
* above-listed licenses.
*/
use std::fmt;
use allocative::Allocative;
use buck2_build_api::analysis::AnalysisResult;
use buck2_build_api::interpreter::rule_defs::provider::collection::FrozenProviderCollection;
use buck2_build_api::interpreter::rule_defs::provider::dependency::Dependency;
use buck2_core::provider::label::ConfiguredProvidersLabel;
use buck2_interpreter::types::configured_providers_label::StarlarkConfiguredProvidersLabel;
use dupe::Dupe;
use starlark::any::ProvidesStaticType;
use starlark::environment::Methods;
use starlark::environment::MethodsBuilder;
use starlark::environment::MethodsStatic;
use starlark::eval::Evaluator;
use starlark::starlark_module;
use starlark::starlark_simple_value;
use starlark::values::FrozenValueTyped;
use starlark::values::NoSerialize;
use starlark::values::StarlarkValue;
use starlark::values::ValueTyped;
use starlark::values::starlark_value;
#[derive(ProvidesStaticType, Debug, NoSerialize, Allocative)]
pub(crate) struct StarlarkAnalysisResult {
// Invariant: The subtarget specified on the label is present in the analysis result.
analysis: AnalysisResult,
label: ConfiguredProvidersLabel,
}
impl fmt::Display for StarlarkAnalysisResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "AnalysisResult(")?;
fmt::Display::fmt(
self.analysis
.lookup_inner(&self.label)
.unwrap()
.provider_collection(),
f,
)?;
write!(f, ")")
}
}
impl StarlarkAnalysisResult {
pub(crate) fn new(
analysis: AnalysisResult,
label: ConfiguredProvidersLabel,
) -> buck2_error::Result<Self> {
// Check that the specified subtarget actually exists
drop(analysis.lookup_inner(&label)?);
Ok(Self { analysis, label })
}
}
starlark_simple_value!(StarlarkAnalysisResult);
#[starlark_value(type = "bxl.AnalysisResult")]
impl<'v> StarlarkValue<'v> for StarlarkAnalysisResult {
fn get_methods() -> Option<&'static Methods> {
static RES: MethodsStatic = MethodsStatic::new();
RES.methods_for_type::<Self::Canonical>(starlark_analysis_result_methods)
}
}
/// The result of running an analysis in bxl.
#[starlark_module]
fn starlark_analysis_result_methods(builder: &mut MethodsBuilder) {
/// Access the providers of the rule. Returns a `ProviderCollection` the same as accessing
/// providers of dependencies within a rule implementation.
///
/// Sample usage:
/// ```python
/// def _impl_providers(ctx):
/// node = ctx.configured_targets("root//bin:the_binary")
/// providers = ctx.analysis(node).providers()
/// ctx.output.print(providers[FooInfo])
/// providers = ctx.analysis("//:bin").providers()
/// ctx.output.print(providers[FooInfo])
/// ```
fn providers<'v>(
this: &'v StarlarkAnalysisResult,
) -> starlark::Result<FrozenValueTyped<'v, FrozenProviderCollection>> {
unsafe {
// SAFETY: this actually just returns a FrozenValue from in the StarlarkAnalysisResult
// which is kept alive for 'v
Ok(this
.analysis
.lookup_inner(&this.label)?
.value()
.value_typed())
}
}
/// Gets the configured providers label for this analysis result.
///
/// Sample usage:
/// ```python
/// def _impl_label(ctx):
/// actions = ctx.aquery().all_actions("//target")
/// for node in actions:
/// if analysis := node.analysis():
/// ctx.output.print(analysis.label())
/// ```
fn label<'v>(
this: &StarlarkAnalysisResult,
) -> starlark::Result<StarlarkConfiguredProvidersLabel> {
Ok(StarlarkConfiguredProvidersLabel::new(this.label.dupe()))
}
/// Converts the analysis result into a `Dependency`. Currently, you can only get a `Dependency` without any
/// transitions. This means that you cannot create an exec dep or toolchain from an analysis result.
///
/// We may support other dependency transition types in the future.
///
/// This is useful for passing in the results of `ctx.analysis()` into anon targets.
///
/// Sample usage:
/// ```python
/// def _impl_dependency(ctx):
/// node = ctx.configured_targets("root//bin:the_binary")
/// dependency = ctx.analysis(node).as_dependency()
/// ```
fn as_dependency<'v>(
this: &'v StarlarkAnalysisResult,
eval: &mut Evaluator<'v, '_, '_>,
) -> starlark::Result<ValueTyped<'v, Dependency<'v>>> {
Ok(eval.heap().alloc_typed(Dependency::new(
eval.heap(),
this.label.dupe(),
this.analysis
.lookup_inner(&this.label)?
.value()
.owned_frozen_value_typed(eval.frozen_heap()),
None,
)))
}
}