From b9d01c1a6189951738ef40b06f529148df809408 Mon Sep 17 00:00:00 2001
From: Martin Nordholts <enselic@gmail.com>
Date: Wed, 22 Sep 2021 09:27:47 +0200
Subject: [PATCH] build_assets.rs: Ignore explicit contexts when tracking
 dependencies

---
 src/assets/build_assets.rs | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/src/assets/build_assets.rs b/src/assets/build_assets.rs
index 2df80594..fcab4ac4 100644
--- a/src/assets/build_assets.rs
+++ b/src/assets/build_assets.rs
@@ -329,10 +329,31 @@ fn dependencies_from_pattern(pattern: &Pattern) -> Vec<OtherSyntax> {
     .collect()
 }
 
+/// Removes any context name from the syntax reference.
+///
+/// When we track dependencies between syntaxes, we are not interested in
+/// dependencies on specific contexts inside other syntaxes. We only care about
+/// the dependency on the syntax itself.
+///
+/// For example, if a syntax includes another syntax like this:
+/// ```yaml
+///   - include: scope:source.c++#unique-variables
+/// ```
+/// we only want to track the dependency on `source.c++`.
+fn remove_explicit_context(scope: Scope) -> Scope {
+    if let Some(without_context) = scope.build_string().split('#').next() {
+        Scope::new(without_context).expect("removing context reference must never fail")
+    } else {
+        scope
+    }
+}
+
 fn dependency_from_context_reference(context_reference: &ContextReference) -> Option<OtherSyntax> {
     match &context_reference {
         ContextReference::File { ref name, .. } => Some(OtherSyntax::ByName(name.clone())),
-        ContextReference::ByScope { ref scope, .. } => Some(OtherSyntax::ByScope(*scope)),
+        ContextReference::ByScope { ref scope, .. } => {
+            Some(OtherSyntax::ByScope(remove_explicit_context(*scope)))
+        }
         _ => None,
     }
 }
@@ -437,3 +458,16 @@ fn asset_to_cache<T: serde::Serialize>(
     println!("okay");
     Ok(())
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn remove_explicit_context_sanity() {
+        // Example from Objective-C++.sublime-syntax
+        let scope = Scope::new("source.c++#unique-variables").unwrap();
+        let expected = Scope::new("source.c++").unwrap();
+        assert_eq!(remove_explicit_context(scope), expected);
+    }
+}