Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 168 additions & 42 deletions crates/hir/src/base_db/source_db.rs

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions crates/hir/src/base_db/source_db/preproc.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use ::preproc::source::{
PreprocSourceId, SourceEmittedTokenId, SourceMacroCallId, SourceMacroReferenceId,
SourcePosition, SourcePreprocError, SourcePreprocModel, SourcePreprocUnavailable, SourceRange,
SourceTokenOrigin,
MacroDefinitionId, PreprocSourceId, SourceEmittedTokenId, SourceMacroCallId,
SourceMacroReferenceId, SourcePosition, SourcePreprocError, SourcePreprocModel,
SourcePreprocUnavailable, SourceRange, SourceTokenOrigin,
};
use rustc_hash::{FxHashMap, FxHashSet};
use smol_str::SmolStr;
use syntax::{SourceBufferOrigin, SyntaxTreeOptions, preproc::Trace};
use syntax::{SourceBufferOrigin, SourceBufferRange, SyntaxTreeOptions, preproc::Trace};
use triomphe::Arc;
use utils::{
line_index::{TextRange, TextSize},
Expand Down Expand Up @@ -37,11 +37,11 @@ pub use self::{
range_index::MappedSourcePreprocModel,
source_map::{
PreprocManifestSource, PreprocSourceMap, PreprocSourceMapError, PreprocSourceMapping,
PreprocSpeculativeUniverseId, PreprocVirtualOrigin,
PreprocSpeculativeUniverseId, PreprocUnavailableReason, PreprocVirtualOrigin,
},
source_mapping::{
preproc_virtual_builtin_path, preproc_virtual_predefines_path,
preproc_virtual_speculative_path,
preproc_virtual_predefines_text, preproc_virtual_speculative_path,
},
};
pub(super) use self::{
Expand Down
8 changes: 3 additions & 5 deletions crates/hir/src/base_db/source_db/preproc/range_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use super::*;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MappedSourcePreprocModel {
pub model: SourcePreprocModel,
pub source_map: PreprocSourceMap,
pub(crate) model: SourcePreprocModel,
pub(crate) source_map: PreprocSourceMap,
range_index: PreprocRangeIndex,
}

Expand Down Expand Up @@ -117,9 +117,7 @@ fn mapped_file_range(
source_map: &PreprocSourceMap,
source_range: SourceRange,
) -> Option<(FileId, TextRange)> {
let range = source_map.map_range(source_range).ok()?;
let file_id = source_map.file_id(source_range.source).ok()?;
Some((file_id, range))
source_map.map_range(source_range).ok()
}

fn sort_indexed_ranges<T: Copy>(ranges: &mut [IndexedRange<T>]) {
Expand Down
62 changes: 39 additions & 23 deletions crates/hir/src/base_db/source_db/preproc/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,40 @@ pub struct PreprocSourceMap {
pub enum PreprocSourceMapping {
RealFile(FileId),
VirtualFile { file_id: FileId, path: VfsPath, origin: PreprocVirtualOrigin },
VirtualDisplay { path: VfsPath, origin: PreprocVirtualOrigin },
Unmapped(SourcePreprocUnavailable),
Unmapped(PreprocUnavailableReason),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PreprocUnavailableReason {
DetachedSource { buffer_id: u32 },
MissingPredefineSourceText { buffer_id: u32 },
UnverifiedPredefineSource { buffer_id: u32 },
MissingMacroCall { call: SourceMacroCallId },
MissingMacroExpansion { call: SourceMacroCallId },
UnknownMacroUsageDefinition { definition: MacroDefinitionId },
}

impl From<SourcePreprocUnavailable> for PreprocUnavailableReason {
fn from(reason: SourcePreprocUnavailable) -> Self {
match reason {
SourcePreprocUnavailable::DetachedSource { source } => {
Self::DetachedSource { buffer_id: source.raw() }
}
SourcePreprocUnavailable::MissingPredefineSourceText { source } => {
Self::MissingPredefineSourceText { buffer_id: source.raw() }
}
SourcePreprocUnavailable::UnverifiedPredefineSource { source } => {
Self::UnverifiedPredefineSource { buffer_id: source.raw() }
}
SourcePreprocUnavailable::MissingMacroCall { call } => Self::MissingMacroCall { call },
SourcePreprocUnavailable::MissingMacroExpansion { call } => {
Self::MissingMacroExpansion { call }
}
SourcePreprocUnavailable::UnknownMacroUsageDefinition { definition } => {
Self::UnknownMacroUsageDefinition { definition }
}
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand All @@ -26,7 +58,7 @@ pub struct PreprocManifestSource {
pub enum PreprocVirtualOrigin {
Predefines { profile: Option<CompilationProfileId> },
Builtin { name: SmolStr },
ExternalIncludeBuffer { source: PreprocSourceId },
ExternalIncludeBuffer { buffer_id: u32 },
Speculative { universe: PreprocSpeculativeUniverseId },
}

Expand All @@ -35,26 +67,10 @@ pub struct PreprocSpeculativeUniverseId(pub u32);

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PreprocSourceMapError {
MissingSource {
source: PreprocSourceId,
},
UnmappedSource {
source: PreprocSourceId,
reason: SourcePreprocUnavailable,
},
RangeOutOfBounds {
source: PreprocSourceId,
range: TextRange,
mapped_range: TextRange,
text_len: usize,
},
MissingEmittedToken {
token: SourceEmittedTokenId,
},
DisplayOnlyVirtualSource {
path: VfsPath,
origin: PreprocVirtualOrigin,
},
MissingSource { buffer_id: u32 },
UnmappedSource { buffer_id: u32, reason: PreprocUnavailableReason },
RangeOutOfBounds { buffer_id: u32, range: TextRange, mapped_range: TextRange, text_len: usize },
MissingEmittedToken { token: SourceEmittedTokenId },
}

mod mapping;
123 changes: 70 additions & 53 deletions crates/hir/src/base_db/source_db/preproc/source_map/mapping.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
use super::*;

impl PreprocSourceMap {
pub fn insert_real_file(&mut self, source: PreprocSourceId, file_id: FileId, text_len: usize) {
pub(crate) fn insert_real_file(
&mut self,
source: PreprocSourceId,
file_id: FileId,
text_len: usize,
) {
self.entries.insert(source, PreprocSourceMapping::RealFile(file_id));
self.predefine_sources.remove(&source);
self.text_lengths.insert(source, text_len);
self.range_offsets.insert(source, 0);
}

pub fn insert_virtual_file(
pub(crate) fn insert_virtual_file(
&mut self,
source: PreprocSourceId,
file_id: Option<FileId>,
file_id: FileId,
path: VfsPath,
origin: PreprocVirtualOrigin,
text_len: usize,
Expand All @@ -22,24 +27,24 @@ impl PreprocSourceMap {
pub(in crate::base_db::source_db::preproc) fn insert_virtual_file_with_offset(
&mut self,
source: PreprocSourceId,
file_id: Option<FileId>,
file_id: FileId,
path: VfsPath,
origin: PreprocVirtualOrigin,
text_len: usize,
range_offset: usize,
) {
let mapping = match file_id {
Some(file_id) => PreprocSourceMapping::VirtualFile { file_id, path, origin },
None => PreprocSourceMapping::VirtualDisplay { path, origin },
};
self.entries.insert(source, mapping);
self.entries.insert(source, PreprocSourceMapping::VirtualFile { file_id, path, origin });
self.predefine_sources.remove(&source);
self.text_lengths.insert(source, text_len);
self.range_offsets.insert(source, range_offset);
}

pub fn insert_unmapped(&mut self, source: PreprocSourceId, reason: SourcePreprocUnavailable) {
self.entries.insert(source, PreprocSourceMapping::Unmapped(reason));
pub(crate) fn insert_unmapped(
&mut self,
source: PreprocSourceId,
reason: SourcePreprocUnavailable,
) {
self.entries.insert(source, PreprocSourceMapping::Unmapped(reason.into()));
self.predefine_sources.remove(&source);
self.text_lengths.remove(&source);
self.range_offsets.remove(&source);
Expand All @@ -53,35 +58,22 @@ impl PreprocSourceMap {
self.predefine_sources.insert(source, manifest_source);
}

pub fn get(&self, source: PreprocSourceId) -> Option<&PreprocSourceMapping> {
pub(crate) fn get(&self, source: PreprocSourceId) -> Option<&PreprocSourceMapping> {
self.entries.get(&source)
}

pub fn predefine_manifest_source(
pub(crate) fn predefine_manifest_source(
&self,
source: PreprocSourceId,
) -> Option<PreprocManifestSource> {
self.predefine_sources.get(&source).copied()
}

pub fn file_id(&self, source: PreprocSourceId) -> Result<FileId, PreprocSourceMapError> {
match self.get(source) {
Some(PreprocSourceMapping::RealFile(file_id)) => Ok(*file_id),
Some(PreprocSourceMapping::VirtualFile { file_id, .. }) => Ok(*file_id),
Some(PreprocSourceMapping::VirtualDisplay { path, origin }) => {
Err(PreprocSourceMapError::DisplayOnlyVirtualSource {
path: path.clone(),
origin: origin.clone(),
})
}
Some(PreprocSourceMapping::Unmapped(reason)) => {
Err(PreprocSourceMapError::UnmappedSource { source, reason: reason.clone() })
}
None => Err(PreprocSourceMapError::MissingSource { source }),
}
pub(crate) fn file_id(&self, source: PreprocSourceId) -> Result<FileId, PreprocSourceMapError> {
self.file_id_for_mapping(source, self.get(source))
}

pub fn source_positions_for_file_offset(
pub(crate) fn source_positions_for_file_offset(
&self,
file_id: FileId,
offset: TextSize,
Expand All @@ -95,7 +87,6 @@ impl PreprocSourceMap {
| PreprocSourceMapping::VirtualFile { file_id: mapped_file_id, .. } => {
*mapped_file_id
}
PreprocSourceMapping::VirtualDisplay { .. } => return None,
PreprocSourceMapping::Unmapped(_) => return None,
};
if mapped_file_id != file_id {
Expand All @@ -113,45 +104,71 @@ impl PreprocSourceMap {
positions
}

pub fn map_range(&self, source_range: SourceRange) -> Result<TextRange, PreprocSourceMapError> {
match self.get(source_range.source) {
Some(PreprocSourceMapping::RealFile(_))
| Some(PreprocSourceMapping::VirtualFile { .. })
| Some(PreprocSourceMapping::VirtualDisplay { .. }) => {}
Some(PreprocSourceMapping::Unmapped(reason)) => {
return Err(PreprocSourceMapError::UnmappedSource {
source: source_range.source,
reason: reason.clone(),
});
}
None => {
return Err(PreprocSourceMapError::MissingSource { source: source_range.source });
}
}
pub(crate) fn map_range(
&self,
source_range: SourceRange,
) -> Result<(FileId, TextRange), PreprocSourceMapError> {
let mapping = self.get(source_range.source);
let file_id = self.file_id_for_mapping(source_range.source, mapping)?;

let range_offset = self.range_offsets.get(&source_range.source).copied().unwrap_or(0);
let mapped_range = shift_text_range(source_range.range, range_offset).ok_or(
PreprocSourceMapError::RangeOutOfBounds {
source: source_range.source,
buffer_id: source_range.source.raw(),
range: source_range.range,
mapped_range: source_range.range,
text_len: usize::MAX,
},
)?;
let text_len = self
.text_lengths
.get(&source_range.source)
.copied()
.ok_or(PreprocSourceMapError::MissingSource { source: source_range.source })?;
let text_len =
self.text_lengths.get(&source_range.source).copied().ok_or(
PreprocSourceMapError::MissingSource { buffer_id: source_range.source.raw() },
)?;
if usize::from(mapped_range.end()) <= text_len {
return Ok(mapped_range);
return Ok((file_id, mapped_range));
}

Err(PreprocSourceMapError::RangeOutOfBounds {
source: source_range.source,
buffer_id: source_range.source.raw(),
range: source_range.range,
mapped_range,
text_len,
})
}

pub(crate) fn map_buffer_range(
&self,
range: &SourceBufferRange,
) -> Option<Result<(FileId, TextRange), PreprocSourceMapError>> {
let source_range = source_range_from_buffer_range(range)?;
Some(self.map_range(source_range))
}

fn file_id_for_mapping(
&self,
source: PreprocSourceId,
mapping: Option<&PreprocSourceMapping>,
) -> Result<FileId, PreprocSourceMapError> {
match mapping {
Some(PreprocSourceMapping::RealFile(file_id)) => Ok(*file_id),
Some(PreprocSourceMapping::VirtualFile { file_id, .. }) => Ok(*file_id),
Some(PreprocSourceMapping::Unmapped(reason)) => {
Err(PreprocSourceMapError::UnmappedSource {
buffer_id: source.raw(),
reason: reason.clone(),
})
}
None => Err(PreprocSourceMapError::MissingSource { buffer_id: source.raw() }),
}
}
}

fn source_range_from_buffer_range(range: &SourceBufferRange) -> Option<SourceRange> {
Some(SourceRange {
source: PreprocSourceId::from(range.buffer_id),
range: TextRange::new(
TextSize::from(u32::try_from(range.range.start).ok()?),
TextSize::from(u32::try_from(range.range.end).ok()?),
),
})
}
Loading
Loading