Skip to content

Commit fdbb4bf

Browse files
robertoaloimeta-codesync[bot]
authored andcommitted
Allow filtering of OTP apps in indexing
Summary: Many applications are included in the Erlang/OTP release, but they are not used by a project. Processing them leads to unnecessary work and memory consumption. This diff adds a new `otp` configuration section to the `.elp.toml` file, allowing users to customize a list of OTP applications to exclude from the analysis. * Add new `OTP` section to ELP Config * Pass reference to the whole ELP configuration to the project loading function * Forward OTP config section to OTP discovery function * Perform filtering * Add documentation on how to use the new feature Reviewed By: TheGeorge Differential Revision: D83974071 fbshipit-source-id: eae11cd06eca9380d00ca5f7a3a70bb659d6ab71
1 parent 86d61bd commit fdbb4bf

File tree

9 files changed

+270
-39
lines changed

9 files changed

+270
-39
lines changed

crates/base_db/src/fixture.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ impl ChangeFixture {
295295
ProjectManifest::discover(&AbsPathBuf::assert(json_config_file.into())).unwrap();
296296
let loaded_project = Project::load(
297297
&manifest,
298-
elp_config.eqwalizer,
298+
&elp_config,
299299
&BuckQueryConfig::BuildGeneratedCode,
300300
&|_| {},
301301
)

crates/elp/src/bin/build_info_cli.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use anyhow::Result;
1616
use elp_ide::elp_ide_db::elp_base_db::AbsPath;
1717
use elp_ide::elp_ide_db::elp_base_db::AbsPathBuf;
1818
use elp_project_model::ElpConfig;
19-
use elp_project_model::EqwalizerConfig;
2019
use elp_project_model::IncludeParentDirs;
2120
use elp_project_model::Project;
2221
use elp_project_model::ProjectBuildData;
@@ -31,8 +30,8 @@ use crate::args::ProjectInfo;
3130
pub(crate) fn save_build_info(args: BuildInfo, query_config: &BuckQueryConfig) -> Result<()> {
3231
let root = fs::canonicalize(&args.project)?;
3332
let root = AbsPathBuf::assert_utf8(root);
34-
let (_elp_config, manifest) = ProjectManifest::discover(&root)?;
35-
let project = Project::load(&manifest, EqwalizerConfig::default(), query_config, &|_| {})?;
33+
let (elp_config, manifest) = ProjectManifest::discover(&root)?;
34+
let project = Project::load(&manifest, &elp_config, query_config, &|_| {})?;
3635
let mut writer = File::create(&args.to)?;
3736
let json_str = serde_json::to_string_pretty::<JsonConfig>(&project.as_json(root))?;
3837
writer.write_all(json_str.as_bytes())?;
@@ -84,7 +83,7 @@ fn load_project(
8483
query_config: &BuckQueryConfig,
8584
) -> Result<(ProjectManifest, Project)> {
8685
let (elp_config, manifest) = ProjectManifest::discover(root)?;
87-
let project = Project::load(&manifest, elp_config.eqwalizer, query_config, &|_| {})?;
86+
let project = Project::load(&manifest, &elp_config, query_config, &|_| {})?;
8887
Ok((manifest, project))
8988
}
9089

@@ -94,6 +93,6 @@ fn load_fallback(
9493
) -> Result<(ProjectManifest, Project)> {
9594
let manifest = ProjectManifest::discover_no_manifest(root, IncludeParentDirs::Yes);
9695
let elp_config = ElpConfig::default();
97-
let project = Project::load(&manifest, elp_config.eqwalizer, query_config, &|_| {})?;
96+
let project = Project::load(&manifest, &elp_config, query_config, &|_| {})?;
9897
Ok((manifest, project))
9998
}

crates/elp/src/build/load.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,7 @@ pub fn load_project_at(
8080

8181
log::info!("Discovered project: {manifest:?}");
8282
let pb = cli.spinner("Loading build info");
83-
let project = Project::load(
84-
&manifest,
85-
elp_config.eqwalizer.clone(),
86-
query_config,
87-
&|_progress| {},
88-
)?;
83+
let project = Project::load(&manifest, &elp_config, query_config, &|_progress| {})?;
8984
pb.finish();
9085

9186
load_project(cli, project, include_otp, eqwalizer_mode)

crates/elp/src/server.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,12 +1724,9 @@ impl Server {
17241724
};
17251725

17261726
spinner.report("Loading project".to_string());
1727-
let mut project = Project::load(
1728-
&manifest,
1729-
elp_config.eqwalizer.clone(),
1730-
query_config,
1731-
&|message| spinner.report(message.to_string()),
1732-
);
1727+
let mut project = Project::load(&manifest, &elp_config, query_config, &|message| {
1728+
spinner.report(message.to_string())
1729+
});
17331730
if let Err(err) = &project {
17341731
log::error!("Failed to load project for manifest {manifest:?}, error: {err:?}");
17351732
match err.downcast_ref::<BuckQueryError>() {
@@ -1745,10 +1742,9 @@ impl Server {
17451742
}
17461743
}
17471744
if !fallback_used {
1748-
project =
1749-
Project::load(&fallback, elp_config.eqwalizer, query_config, &|message| {
1750-
spinner.report(message.to_string())
1751-
});
1745+
project = Project::load(&fallback, &elp_config, query_config, &|message| {
1746+
spinner.report(message.to_string())
1747+
});
17521748
if let Err(err) = &project {
17531749
log::error!(
17541750
"Failed to load project for fallback manifest {manifest:?}, error: {err:?}"

crates/elp/tests/slow-tests/buck_tests.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,8 @@ mod tests {
8282
let (elp_config, buck_config) =
8383
ProjectManifest::discover(&to_abs_path_buf(&path).unwrap()).unwrap();
8484

85-
let project = Project::load(
86-
&buck_config,
87-
elp_config.eqwalizer,
88-
&BUCK_QUERY_CONFIG,
89-
&|_| {},
90-
)
91-
.unwrap();
85+
let project =
86+
Project::load(&buck_config, &elp_config, &BUCK_QUERY_CONFIG, &|_| {}).unwrap();
9287

9388
let project_data: Vec<ProjectAppData> = project
9489
.non_otp_apps()

crates/project_model/src/buck.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ impl IncludeMapping {
326326
impl BuckProject {
327327
pub fn load_from_config(
328328
buck_conf: &BuckConfig,
329+
elp_config: &ElpConfig,
329330
query_config: &BuckQueryConfig,
330331
report_progress: &impl Fn(&str),
331332
) -> Result<
@@ -349,7 +350,7 @@ impl BuckProject {
349350
};
350351
let otp_root = Otp::find_otp()?;
351352
// TODO: we now get these twice. Perhaps they should be cached?
352-
let (_otp, otp_project_apps) = Otp::discover(otp_root.clone());
353+
let (_otp, otp_project_apps) = Otp::discover(otp_root.clone(), &elp_config.otp);
353354
include_mapping.add_otp(&otp_project_apps);
354355
Ok((
355356
project,

crates/project_model/src/lib.rs

Lines changed: 156 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ pub struct ElpConfig {
385385
pub eqwalizer: EqwalizerConfig,
386386
#[serde(default)]
387387
pub rebar: ElpRebarConfig,
388+
#[serde(default)]
389+
pub otp: OtpConfig,
388390
}
389391

390392
#[derive(
@@ -501,6 +503,22 @@ impl Default for ElpRebarConfig {
501503
}
502504
}
503505

506+
#[derive(
507+
Debug,
508+
Default,
509+
Clone,
510+
PartialEq,
511+
Eq,
512+
Hash,
513+
Ord,
514+
PartialOrd,
515+
Deserialize,
516+
Serialize
517+
)]
518+
pub struct OtpConfig {
519+
pub exclude_apps: Vec<String>,
520+
}
521+
504522
impl ElpConfig {
505523
pub fn new(
506524
config_path: AbsPathBuf,
@@ -515,6 +533,7 @@ impl ElpConfig {
515533
build_info,
516534
eqwalizer,
517535
rebar,
536+
otp: OtpConfig::default(),
518537
}
519538
}
520539
pub fn try_parse(path: &AbsPath) -> Result<ElpConfig> {
@@ -998,7 +1017,7 @@ impl Project {
9981017

9991018
pub fn load(
10001019
manifest: &ProjectManifest,
1001-
eqwalizer_config: EqwalizerConfig,
1020+
elp_config: &ElpConfig,
10021021
query_config: &BuckQueryConfig,
10031022
report_progress: &impl Fn(&str),
10041023
) -> Result<Project> {
@@ -1032,7 +1051,7 @@ impl Project {
10321051
ProjectManifest::TomlBuck(buck) => {
10331052
// We only select this manifest if buck is actually enabled
10341053
let (project, apps, otp_root, include_mapping) =
1035-
BuckProject::load_from_config(buck, query_config, report_progress)?;
1054+
BuckProject::load_from_config(buck, elp_config, query_config, report_progress)?;
10361055
(
10371056
ProjectBuildData::Buck(project),
10381057
apps,
@@ -1061,14 +1080,14 @@ impl Project {
10611080
}
10621081
};
10631082

1064-
let (otp, otp_project_apps) = Otp::discover(otp_root);
1083+
let (otp, otp_project_apps) = Otp::discover(otp_root, &elp_config.otp);
10651084
project_apps.extend(otp_project_apps);
10661085
report_progress("Project info loaded");
10671086
Ok(Project {
10681087
otp,
10691088
project_build_data: project_build_info,
10701089
project_apps,
1071-
eqwalizer_config,
1090+
eqwalizer_config: elp_config.eqwalizer.clone(),
10721091
include_mapping,
10731092
})
10741093
}
@@ -1172,6 +1191,9 @@ mod tests {
11721191
rebar: ElpRebarConfig {
11731192
profile: "test",
11741193
},
1194+
otp: OtpConfig {
1195+
exclude_apps: [],
1196+
},
11751197
},
11761198
Rebar(
11771199
RebarConfig {
@@ -1237,6 +1259,9 @@ mod tests {
12371259
rebar: ElpRebarConfig {
12381260
profile: "test",
12391261
},
1262+
otp: OtpConfig {
1263+
exclude_apps: [],
1264+
},
12401265
},
12411266
Json(
12421267
JsonConfig {
@@ -1347,6 +1372,9 @@ mod tests {
13471372
rebar: ElpRebarConfig {
13481373
profile: "test",
13491374
},
1375+
otp: OtpConfig {
1376+
exclude_apps: [],
1377+
},
13501378
},
13511379
JsonConfig {
13521380
apps: [
@@ -1502,6 +1530,9 @@ mod tests {
15021530
rebar: ElpRebarConfig {
15031531
profile: "test",
15041532
},
1533+
otp: OtpConfig {
1534+
exclude_apps: [],
1535+
},
15051536
},
15061537
NoManifest(
15071538
NoManifestConfig {
@@ -1571,6 +1602,9 @@ mod tests {
15711602
rebar: ElpRebarConfig {
15721603
profile: "test",
15731604
},
1605+
otp: OtpConfig {
1606+
exclude_apps: [],
1607+
},
15741608
},
15751609
NoManifest(
15761610
NoManifestConfig {
@@ -1764,6 +1798,9 @@ mod tests {
17641798
rebar: ElpRebarConfig {
17651799
profile: "other",
17661800
},
1801+
otp: OtpConfig {
1802+
exclude_apps: [],
1803+
},
17671804
}
17681805
"#]]
17691806
.assert_eq(&debug_normalise_temp_dir(dir, &elp_config));
@@ -1807,6 +1844,7 @@ mod tests {
18071844
rebar: ElpRebarConfig {
18081845
profile: "my_profile".to_string(),
18091846
},
1847+
otp: OtpConfig::default(),
18101848
})
18111849
.unwrap();
18121850
expect![[r#"
@@ -1829,6 +1867,9 @@ mod tests {
18291867
18301868
[rebar]
18311869
profile = "my_profile"
1870+
1871+
[otp]
1872+
exclude_apps = []
18321873
"#]]
18331874
.assert_eq(&result);
18341875
}
@@ -1902,6 +1943,9 @@ mod tests {
19021943
rebar: ElpRebarConfig {
19031944
profile: "my_profile",
19041945
},
1946+
otp: OtpConfig {
1947+
exclude_apps: [],
1948+
},
19051949
}
19061950
"#]]
19071951
.assert_debug_eq(&lints);
@@ -2017,4 +2061,112 @@ mod tests {
20172061
}
20182062
}
20192063
}
2064+
2065+
#[test]
2066+
fn test_toml_otp_exclude_apps() {
2067+
let spec = r#"
2068+
//- /.elp.toml
2069+
[otp]
2070+
exclude_apps = ["megaco", "eunit"]
2071+
//- /app_a/src/app.erl
2072+
-module(app).
2073+
"#;
2074+
let dir = FixtureWithProjectMeta::gen_project(spec);
2075+
if let Ok((elp_config, ProjectManifest::NoManifest(_))) = ProjectManifest::discover(
2076+
&to_abs_path_buf(&dir.path().join("app_a/src/app.erl")).unwrap(),
2077+
) {
2078+
expect![[r#"
2079+
ElpConfig {
2080+
config_path: Some(
2081+
AbsPathBuf(
2082+
"TMPDIR/.elp.toml",
2083+
),
2084+
),
2085+
build_info: None,
2086+
buck: None,
2087+
eqwalizer: EqwalizerConfig {
2088+
enable_all: true,
2089+
max_tasks: 4,
2090+
ignore_modules: [],
2091+
ignore_modules_compiled_patterns: [],
2092+
},
2093+
rebar: ElpRebarConfig {
2094+
profile: "test",
2095+
},
2096+
otp: OtpConfig {
2097+
exclude_apps: [
2098+
"megaco",
2099+
"eunit",
2100+
],
2101+
},
2102+
}
2103+
"#]]
2104+
.assert_eq(&debug_normalise_temp_dir(dir, &elp_config));
2105+
} else {
2106+
panic!()
2107+
}
2108+
}
2109+
2110+
#[test]
2111+
fn serde_serialize_elp_toml_with_otp() {
2112+
let result = toml::to_string::<ElpConfig>(&ElpConfig {
2113+
config_path: None,
2114+
build_info: None,
2115+
buck: None,
2116+
eqwalizer: EqwalizerConfig::default(),
2117+
rebar: ElpRebarConfig::default(),
2118+
otp: OtpConfig {
2119+
exclude_apps: vec!["megaco".to_string(), "eunit".to_string()],
2120+
},
2121+
})
2122+
.unwrap();
2123+
expect![[r#"
2124+
[eqwalizer]
2125+
enable_all = true
2126+
max_tasks = 4
2127+
ignore_modules = []
2128+
2129+
[rebar]
2130+
profile = "test"
2131+
2132+
[otp]
2133+
exclude_apps = ["megaco", "eunit"]
2134+
"#]]
2135+
.assert_eq(&result);
2136+
}
2137+
2138+
#[test]
2139+
fn serde_deserialize_elp_toml_with_otp() {
2140+
let config: ElpConfig = toml::from_str(
2141+
r#"
2142+
[otp]
2143+
exclude_apps = ["megaco", "eunit"]
2144+
"#,
2145+
)
2146+
.unwrap();
2147+
2148+
expect![[r#"
2149+
ElpConfig {
2150+
config_path: None,
2151+
build_info: None,
2152+
buck: None,
2153+
eqwalizer: EqwalizerConfig {
2154+
enable_all: true,
2155+
max_tasks: 4,
2156+
ignore_modules: [],
2157+
ignore_modules_compiled_patterns: [],
2158+
},
2159+
rebar: ElpRebarConfig {
2160+
profile: "test",
2161+
},
2162+
otp: OtpConfig {
2163+
exclude_apps: [
2164+
"megaco",
2165+
"eunit",
2166+
],
2167+
},
2168+
}
2169+
"#]]
2170+
.assert_debug_eq(&config);
2171+
}
20202172
}

0 commit comments

Comments
 (0)