Skip to content

Commit

Permalink
refactor: track too large files inside workspace server
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr committed Dec 15, 2024
1 parent e77fb9d commit b90cbe3
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
2 changes: 1 addition & 1 deletion crates/biome_service/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ pub struct FileIgnored {
path: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FileTooLarge {
pub size: usize,
pub limit: usize,
Expand Down
44 changes: 34 additions & 10 deletions crates/biome_service/src/workspace/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::{
SearchResults, SetManifestForProjectParams, SupportsFeatureParams,
UnregisterProjectFolderParams, UpdateSettingsParams,
};
use crate::diagnostics::{InvalidPattern, NoProject, SearchError};
use crate::diagnostics::{FileTooLarge, InvalidPattern, NoProject, SearchError};
use crate::file_handlers::{
Capabilities, CodeActionsParams, DocumentFileSource, FixAllParams, LintParams, ParseResult,
};
Expand Down Expand Up @@ -103,7 +103,7 @@ pub(crate) struct Document {
pub(crate) file_source_index: usize,

/// The result of the parser (syntax tree + diagnostics).
pub(crate) syntax: AnyParse,
pub(crate) syntax: Result<AnyParse, FileTooLarge>,

/// If `true`, this indicates the document has been opened by the scanner,
/// and should be unloaded only when the project is unregistered.
Expand Down Expand Up @@ -260,6 +260,23 @@ impl WorkspaceServer {
};

let mut index = self.set_source(source);

let size = content.as_bytes().len();
let limit = self.settings.get_max_file_size();
if size > limit {
self.documents.pin().insert(
params.path,
Document {
content,
version: params.version,
file_source_index: index,
syntax: Err(FileTooLarge { size, limit }),
opened_by_scanner,
},
);
return Ok(());
}

let mut node_cache = NodeCache::default();
let parsed = self.parse(&params.path, &content, index, &mut node_cache)?;

Expand All @@ -279,7 +296,7 @@ impl WorkspaceServer {
content,
version: params.version,
file_source_index: index,
syntax: parsed.any_parse,
syntax: Ok(parsed.any_parse),
opened_by_scanner,
};

Expand Down Expand Up @@ -341,15 +358,22 @@ impl WorkspaceServer {
Ok(())
}

/// Retrieves the parser result for a given file, calculating it if the file was not yet parsed.
/// Retrieves the parser result for a given file.
///
/// Returns an error if no file exists in the workspace with this path.
fn get_parse(&self, biome_path: &BiomePath) -> Result<AnyParse, WorkspaceError> {
self.documents
.pin()
let documents = self.documents.pin();
let syntax = documents
.get(biome_path)
.map(|document| document.syntax.clone())
.ok_or_else(WorkspaceError::not_found)
.map(|document| document.syntax.as_ref())
.ok_or_else(WorkspaceError::not_found)?;

match syntax {
Ok(syntax) => Ok(syntax.clone()),
Err(FileTooLarge { .. }) => Err(WorkspaceError::file_ignored(
biome_path.to_string_lossy().to_string(),
)),
}
}

fn parse(
Expand Down Expand Up @@ -541,7 +565,7 @@ impl Workspace for WorkspaceServer {
content: params.content,
version: params.version,
file_source_index: index,
syntax: parsed.into(),
syntax: Ok(parsed.into()),
opened_by_scanner: false,
},
);
Expand Down Expand Up @@ -720,7 +744,7 @@ impl Workspace for WorkspaceServer {
content: params.content,
version: params.version,
file_source_index: index,
syntax: parsed.any_parse,
syntax: Ok(parsed.any_parse),
opened_by_scanner,
};

Expand Down
46 changes: 44 additions & 2 deletions crates/biome_service/tests/workspace.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
#[cfg(test)]
mod test {
use std::num::NonZero;
use std::path::PathBuf;

use biome_analyze::RuleCategories;
use biome_configuration::analyzer::{RuleGroup, RuleSelector};
use biome_configuration::{PartialConfiguration, PartialFilesConfiguration};
use biome_fs::{BiomePath, MemoryFileSystem};
use biome_js_syntax::{JsFileSource, TextSize};
use biome_service::file_handlers::DocumentFileSource;
use biome_service::workspace::{
server, CloseFileParams, FileContent, FileGuard, GetFileContentParams, OpenFileParams,
RegisterProjectFolderParams, UnregisterProjectFolderParams,
server, CloseFileParams, FileContent, FileGuard, GetFileContentParams, GetSyntaxTreeParams,
OpenFileParams, RegisterProjectFolderParams, UnregisterProjectFolderParams,
UpdateSettingsParams,
};
use biome_service::{Workspace, WorkspaceError};

Expand Down Expand Up @@ -363,4 +366,43 @@ type User {
})
.is_err_and(|error| matches!(error, WorkspaceError::NotFound(_))));
}

#[test]
fn too_large_files_are_tracked_but_not_parsed() {
const FILE_CONTENT: &[u8] = b"console.log(`I'm YUUUGE!`);";

let mut fs = MemoryFileSystem::default();
fs.insert(PathBuf::from("/project/a.ts"), FILE_CONTENT);

let workspace = server(Box::new(fs));
workspace
.register_project_folder(RegisterProjectFolderParams {
set_as_current_workspace: true,
path: Some(PathBuf::from("/project")),
})
.unwrap();

workspace
.update_settings(UpdateSettingsParams {
configuration: PartialConfiguration {
files: Some(PartialFilesConfiguration {
max_size: NonZero::new(10),
..Default::default()
}),
..Default::default()
},
vcs_base_path: None,
gitignore_matches: Vec::new(),
workspace_directory: None,
})
.unwrap();

workspace.scan_current_project_folder(()).unwrap();

assert!(workspace
.get_syntax_tree(GetSyntaxTreeParams {
path: BiomePath::new("/project/a.ts"),
})
.is_err_and(|error| matches!(error, WorkspaceError::FileIgnored(_))));
}
}

0 comments on commit b90cbe3

Please sign in to comment.