diff --git a/.travis.yml b/.travis.yml index ed4ef10b..fb49f594 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,35 @@ language: rust cache: cargo + rust: - stable - beta - nightly + +env: + - CARGO_FEATURES="" + REPORTING_CARGO_FEATURES="" + - CARGO_FEATURES="memory_usage" + REPORTING_CARGO_FEATURES="memory_usage" + - CARGO_FEATURES="serialization" + REPORTING_CARGO_FEATURES="" + matrix: allow_failures: - rust: nightly fast_finish: true + +script: + - set -ex + # We manually build/test each crate and pass in any necessary feature flags + # to work around rust-lang/cargo#4942 + + # codespan + - cargo build --manifest-path=codespan/Cargo.toml --verbose --no-default-features --features="$CARGO_FEATURES" + - cargo test --manifest-path=codespan/Cargo.toml --verbose --no-default-features --features="$CARGO_FEATURES" + # codespan-lsp + - cargo build --manifest-path=codespan-lsp/Cargo.toml --verbose + - cargo test --manifest-path=codespan-lsp/Cargo.toml --verbose + # codespan-reporting + - cargo build --manifest-path=codespan-reporting/Cargo.toml --verbose --no-default-features --features="$REPORTING_CARGO_FEATURES" + - cargo test --manifest-path=codespan-reporting/Cargo.toml --verbose --no-default-features --features="$REPORTING_CARGO_FEATURES" diff --git a/codespan-reporting/Cargo.toml b/codespan-reporting/Cargo.toml index d996c5f3..9a1b5df2 100644 --- a/codespan-reporting/Cargo.toml +++ b/codespan-reporting/Cargo.toml @@ -13,6 +13,11 @@ exclude = ["assets/**"] [dependencies] codespan = { path = "../codespan", version = "0.1.1" } termcolor = "0.3.4" +heapsize = { version = "0.4", optional = true } +heapsize_derive = { version = "0.1", optional = true } [dev-dependencies] structopt = "0.2.7" + +[features] +memory_usage = ["heapsize_derive", "heapsize", "codespan/memory_usage"] diff --git a/codespan-reporting/src/diagnostic.rs b/codespan-reporting/src/diagnostic.rs index ac4663cb..e2b63bf8 100644 --- a/codespan-reporting/src/diagnostic.rs +++ b/codespan-reporting/src/diagnostic.rs @@ -6,6 +6,7 @@ use Severity; /// A style for the label #[derive(Copy, Clone, PartialEq, Debug)] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub enum LabelStyle { /// The main focus of the diagnostic Primary, @@ -15,6 +16,7 @@ pub enum LabelStyle { /// A label describing an underlined region of code associated with a diagnostic #[derive(Clone, Debug)] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct Label { /// The span we are going to include in the final snippet. pub span: ByteSpan, @@ -49,6 +51,7 @@ impl Label { /// Represents a diagnostic message and associated child messages. #[derive(Clone, Debug)] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct Diagnostic { /// The overall severity of the diagnostic pub severity: Severity, diff --git a/codespan-reporting/src/lib.rs b/codespan-reporting/src/lib.rs index 11a59bb2..f3d7cc96 100644 --- a/codespan-reporting/src/lib.rs +++ b/codespan-reporting/src/lib.rs @@ -5,6 +5,11 @@ use std::cmp::Ordering; use std::fmt; use std::str::FromStr; use termcolor::{Color, ColorChoice}; +#[cfg(feature = "memory_usage")] +extern crate heapsize; +#[cfg(feature = "memory_usage")] +#[macro_use] +extern crate heapsize_derive; mod diagnostic; mod emitter; @@ -25,6 +30,7 @@ pub use self::emitter::emit; /// assert!(Severity::Note > Severity::Help); /// ``` #[derive(Copy, Clone, PartialEq, Hash, Debug)] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub enum Severity { /// An unexpected bug. Bug, diff --git a/codespan/Cargo.toml b/codespan/Cargo.toml index 4b81e911..7b6e34e0 100644 --- a/codespan/Cargo.toml +++ b/codespan/Cargo.toml @@ -14,10 +14,12 @@ failure = "0.1.1" serde_derive = { version = "1", optional = true } serde = { version = "1", optional = true } itertools = "0.7" +heapsize = { version = "0.4", optional = true } +heapsize_derive = { version = "0.1", optional = true } [dev-dependencies] pretty_assertions = "0.5.0" - [features] serialization = ["serde", "serde/rc", "serde_derive"] +memory_usage = ["heapsize_derive", "heapsize"] diff --git a/codespan/src/codemap.rs b/codespan/src/codemap.rs index 38750eb7..1203c0e6 100644 --- a/codespan/src/codemap.rs +++ b/codespan/src/codemap.rs @@ -9,6 +9,7 @@ use index::{ByteIndex, ByteOffset, RawIndex}; #[derive(Clone, Debug, Default)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct CodeMap { files: Vec>, } diff --git a/codespan/src/filemap.rs b/codespan/src/filemap.rs index cce8a2f6..418bebf4 100644 --- a/codespan/src/filemap.rs +++ b/codespan/src/filemap.rs @@ -4,6 +4,8 @@ use std::borrow::Cow; use std::path::{Path, PathBuf}; use std::{fmt, io}; +#[cfg(feature = "memory_usage")] +use heapsize::{self, HeapSizeOf}; use index::{ByteIndex, ByteOffset, ColumnIndex, LineIndex, LineOffset, RawIndex, RawOffset}; use span::ByteSpan; @@ -59,6 +61,28 @@ impl fmt::Display for FileName { } } +#[cfg(feature = "memory_usage")] +impl HeapSizeOf for FileName { + fn heap_size_of_children(&self) -> usize { + match *self { + FileName::Virtual(ref s) => s.heap_size_of_children(), + FileName::Real(ref path) => { + // Reliably finding the amount of memory used by a `PathBuf` is + // annoying due to its os-specific nature. We use an + // approximation by converting to a string and getting the + // raw heap size for the string's buffer, falling back to 0 + // otherwise. Ideally this should be in the `heapsize` crate. + // + // This *should* be safe because a `PathBuf` will allocate its + // buffer using jemalloc. + path.to_str() + .map(|s| unsafe { heapsize::heap_size_of(s.as_ptr()) }) + .unwrap_or(0) + } + } + } +} + #[derive(Debug, Fail, PartialEq)] pub enum LineIndexError { #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)] @@ -92,6 +116,7 @@ pub enum SpanError { #[derive(Debug)] #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] /// Some source code pub struct FileMap { /// The name of the file that the source came from diff --git a/codespan/src/index.rs b/codespan/src/index.rs index d123d7bb..05e7d9dd 100644 --- a/codespan/src/index.rs +++ b/codespan/src/index.rs @@ -13,6 +13,7 @@ pub type RawOffset = i64; /// A zero-indexed line offset into a source file #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct LineIndex(pub RawIndex); impl LineIndex { @@ -51,6 +52,7 @@ impl fmt::Debug for LineIndex { /// A 1-indexed line number. Useful for pretty printing source locations. #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct LineNumber(RawIndex); impl fmt::Debug for LineNumber { @@ -70,6 +72,7 @@ impl fmt::Display for LineNumber { /// A line offset in a source file #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct LineOffset(pub RawOffset); impl Default for LineOffset { @@ -95,6 +98,7 @@ impl fmt::Display for LineOffset { /// A zero-indexed column offset into a source file #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct ColumnIndex(pub RawIndex); impl ColumnIndex { @@ -133,6 +137,7 @@ impl fmt::Debug for ColumnIndex { /// A 1-indexed column number. Useful for pretty printing source locations. #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct ColumnNumber(RawIndex); impl fmt::Debug for ColumnNumber { @@ -152,6 +157,7 @@ impl fmt::Display for ColumnNumber { /// A column offset in a source file #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct ColumnOffset(pub RawOffset); impl Default for ColumnOffset { @@ -177,6 +183,7 @@ impl fmt::Display for ColumnOffset { /// A byte position in a source file #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct ByteIndex(pub RawIndex); impl ByteIndex { @@ -214,6 +221,7 @@ impl fmt::Display for ByteIndex { /// A byte offset in a source file #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct ByteOffset(pub RawOffset); impl ByteOffset { diff --git a/codespan/src/lib.rs b/codespan/src/lib.rs index cf6fe6ab..72987f8b 100644 --- a/codespan/src/lib.rs +++ b/codespan/src/lib.rs @@ -8,6 +8,8 @@ //! //! - **serialization** - Adds `Serialize` and `Deserialize` implementations //! for use with `serde` +//! - **memory_usage** - Adds `HeapSizeOf` implementations for use with the +//! `heapsize` crate #[macro_use] extern crate failure; @@ -22,6 +24,12 @@ extern crate serde; #[macro_use] extern crate serde_derive; +#[cfg(feature = "memory_usage")] +extern crate heapsize; +#[cfg(feature = "memory_usage")] +#[macro_use] +extern crate heapsize_derive; + mod codemap; mod filemap; mod index; diff --git a/codespan/src/span.rs b/codespan/src/span.rs index 5e783d0e..3c0f299d 100644 --- a/codespan/src/span.rs +++ b/codespan/src/span.rs @@ -6,6 +6,7 @@ use index::{ByteIndex, Index}; /// A region of code in a source file #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Ord, PartialOrd)] #[cfg_attr(feature = "serialization", derive(Deserialize, Serialize))] +#[cfg_attr(feature = "memory_usage", derive(HeapSizeOf))] pub struct Span { start: I, end: I,