diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 4be55126b862..fcc0bb0b5138 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -713,6 +713,7 @@ impl ExpansionInfo {
         &self,
         db: &dyn db::ExpandDatabase,
         token: InFile<&SyntaxToken>,
+        ignore_included_file: bool,
     ) -> Option<(InFile<SyntaxToken>, Origin)> {
         assert_eq!(token.file_id, self.expanded.file_id.into());
         // Fetch the id through its text range,
@@ -724,7 +725,7 @@ impl ExpansionInfo {
         let loc = db.lookup_intern_macro_call(call_id);
 
         // Special case: map tokens from `include!` expansions to the included file
-        if loc.def.is_include() {
+        if loc.def.is_include() && !ignore_included_file {
             if let Ok((tt_and_map, file_id)) = db.include_expand(call_id) {
                 let range = tt_and_map.1.first_range_by_token(token_id, token.value.kind())?;
                 let source = db.parse(file_id);
@@ -954,6 +955,23 @@ impl InFile<&SyntaxNode> {
         }
     }
 
+    pub fn original_file_range_ignore_included_file(
+        self,
+        db: &dyn db::ExpandDatabase,
+    ) -> FileRange {
+        match self.file_id.repr() {
+            HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
+            HirFileIdRepr::MacroFile(mac_file) => {
+                if let Some(res) = self.original_file_range_opt_ignore_included_file(db) {
+                    return res;
+                }
+                // Fall back to whole macro call.
+                let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
+                loc.kind.original_call_range(db)
+            }
+        }
+    }
+
     /// Falls back to the macro call range if the node cannot be mapped up fully.
     pub fn original_file_range_full(self, db: &dyn db::ExpandDatabase) -> FileRange {
         match self.file_id.repr() {
@@ -971,7 +989,29 @@ impl InFile<&SyntaxNode> {
 
     /// Attempts to map the syntax node back up its macro calls.
     pub fn original_file_range_opt(self, db: &dyn db::ExpandDatabase) -> Option<FileRange> {
-        match ascend_node_border_tokens(db, self) {
+        match ascend_node_border_tokens(db, self, false) {
+            Some(InFile { file_id, value: (first, last) }) => {
+                let original_file = file_id.original_file(db);
+                let range = first.text_range().cover(last.text_range());
+                if file_id != original_file.into() {
+                    tracing::error!("Failed mapping up more for {:?}", range);
+                    return None;
+                }
+                Some(FileRange { file_id: original_file, range })
+            }
+            _ if !self.file_id.is_macro() => Some(FileRange {
+                file_id: self.file_id.original_file(db),
+                range: self.value.text_range(),
+            }),
+            _ => None,
+        }
+    }
+
+    pub fn original_file_range_opt_ignore_included_file(
+        self,
+        db: &dyn db::ExpandDatabase,
+    ) -> Option<FileRange> {
+        match ascend_node_border_tokens(db, self, true) {
             Some(InFile { file_id, value: (first, last) }) => {
                 let original_file = file_id.original_file(db);
                 let range = first.text_range().cover(last.text_range());
@@ -998,7 +1038,8 @@ impl InFile<&SyntaxNode> {
             return None;
         }
 
-        if let Some(InFile { file_id, value: (first, last) }) = ascend_node_border_tokens(db, self)
+        if let Some(InFile { file_id, value: (first, last) }) =
+            ascend_node_border_tokens(db, self, false)
         {
             if file_id.is_macro() {
                 let range = first.text_range().cover(last.text_range());
@@ -1018,7 +1059,7 @@ impl InFile<&SyntaxNode> {
 impl InFile<SyntaxToken> {
     pub fn upmap(self, db: &dyn db::ExpandDatabase) -> Option<InFile<SyntaxToken>> {
         let expansion = self.file_id.expansion_info(db)?;
-        expansion.map_token_up(db, self.as_ref()).map(|(it, _)| it)
+        expansion.map_token_up(db, self.as_ref(), false).map(|(it, _)| it)
     }
 
     /// Falls back to the macro call range if the node cannot be mapped up fully.
@@ -1044,7 +1085,7 @@ impl InFile<SyntaxToken> {
             }
             HirFileIdRepr::MacroFile(_) => {
                 let expansion = self.file_id.expansion_info(db)?;
-                let InFile { file_id, value } = ascend_call_token(db, &expansion, self)?;
+                let InFile { file_id, value } = ascend_call_token(db, &expansion, self, false)?;
                 let original_file = file_id.original_file(db);
                 if file_id != original_file.into() {
                     return None;
@@ -1070,6 +1111,7 @@ impl<T> From<InMacroFile<T>> for InFile<T> {
 fn ascend_node_border_tokens(
     db: &dyn db::ExpandDatabase,
     InFile { file_id, value: node }: InFile<&SyntaxNode>,
+    ignore_included_file: bool,
 ) -> Option<InFile<(SyntaxToken, SyntaxToken)>> {
     let expansion = file_id.expansion_info(db)?;
 
@@ -1079,8 +1121,9 @@ fn ascend_node_border_tokens(
     // FIXME: Once the token map rewrite is done, this shouldnt need to rely on syntax nodes and tokens anymore
     let first = first_token(node)?;
     let last = last_token(node)?;
-    let first = ascend_call_token(db, &expansion, InFile::new(file_id, first))?;
-    let last = ascend_call_token(db, &expansion, InFile::new(file_id, last))?;
+    let first =
+        ascend_call_token(db, &expansion, InFile::new(file_id, first), ignore_included_file)?;
+    let last = ascend_call_token(db, &expansion, InFile::new(file_id, last), ignore_included_file)?;
     (first.file_id == last.file_id).then(|| InFile::new(first.file_id, (first.value, last.value)))
 }
 
@@ -1088,11 +1131,12 @@ fn ascend_call_token(
     db: &dyn db::ExpandDatabase,
     expansion: &ExpansionInfo,
     token: InFile<SyntaxToken>,
+    ignore_included_file: bool,
 ) -> Option<InFile<SyntaxToken>> {
-    let mut mapping = expansion.map_token_up(db, token.as_ref())?;
+    let mut mapping = expansion.map_token_up(db, token.as_ref(), ignore_included_file)?;
     while let (mapped, Origin::Call) = mapping {
         match mapped.file_id.expansion_info(db) {
-            Some(info) => mapping = info.map_token_up(db, mapped.as_ref())?,
+            Some(info) => mapping = info.map_token_up(db, mapped.as_ref(), ignore_included_file)?,
             None => return Some(mapped),
         }
     }
@@ -1115,7 +1159,7 @@ impl<N: AstNode> InFile<N> {
         }
 
         if let Some(InFile { file_id, value: (first, last) }) =
-            ascend_node_border_tokens(db, self.syntax())
+            ascend_node_border_tokens(db, self.syntax(), false)
         {
             if file_id.is_macro() {
                 let range = first.text_range().cover(last.text_range());
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index a42e0978b25f..7242024dcbb7 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -733,6 +733,11 @@ impl<'db> SemanticsImpl<'db> {
         node.original_file_range(self.db.upcast())
     }
 
+    pub fn original_range_ignore_included_file(&self, node: &SyntaxNode) -> FileRange {
+        let node = self.find_file(node);
+        node.original_file_range_ignore_included_file(self.db.upcast())
+    }
+
     /// Attempts to map the node out of macro expanded files returning the original file range.
     pub fn original_range_opt(&self, node: &SyntaxNode) -> Option<FileRange> {
         let node = self.find_file(node);
diff --git a/crates/ide-diagnostics/src/handlers/macro_error.rs b/crates/ide-diagnostics/src/handlers/macro_error.rs
index 7ca0a0eab2b6..c80fd3fc5452 100644
--- a/crates/ide-diagnostics/src/handlers/macro_error.rs
+++ b/crates/ide-diagnostics/src/handlers/macro_error.rs
@@ -268,4 +268,25 @@ fn f() {
 "#,
         )
     }
+
+    #[test]
+    fn include_does_not_break_diagnostics() {
+        let mut config = DiagnosticsConfig::test_sample();
+
+        config.disabled.insert("unlinked-file".to_string());
+
+        check_diagnostics_with_config(
+            config,
+            r#"
+//- minicore: include
+//- /lib.rs crate:lib
+    include!("include-me.rs");
+  //^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unresolved macro `err`
+//- /include-me.rs
+/// long doc that pushes the diagnostic range beyond the first file's text length
+    #[err]
+    mod prim_never {}
+"#,
+        );
+    }
 }
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index fe5567544e83..b52912c0e890 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -268,7 +268,9 @@ impl DiagnosticsContext<'_> {
             let precise_location = precise_location?;
             let root = sema.parse_or_expand(node.file_id);
             match root.covering_element(precise_location) {
-                syntax::NodeOrToken::Node(it) => Some(sema.original_range(&it)),
+                syntax::NodeOrToken::Node(it) => {
+                    Some(sema.original_range_ignore_included_file(&it))
+                }
                 syntax::NodeOrToken::Token(it) => {
                     node.with_value(it).original_file_range_opt(sema.db)
                 }