[Canonical page](<https://docs.dhtmlx.com/planning-engine/rust/api/project-analyze/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Project::analyze

Computes analytics over dates without scheduling them. It reads either supplied [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>) or the current dates of a [`Project`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md>), including unsolved edits. It never installs data and never changes the solved status.

## Signature

```rust
pub fn analyze(
    &self,
    data: Option<&ProjectData>,
    options: &AnalyzeOptions,
) -> Result<ScheduleResult, Error>
```

Takes `&self`. Synchronous and CPU-only. Works on an unsolved project.

## Parameters

| Name | Type | Description |
|---|---|---|
| `data` | `Option<&`[`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>)`>` | Dates to analyze, or `None` for the project's current dates |
| `options` | `&`[`AnalyzeOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/analyze-options.md>) | Which analytics to compute |

## Returns

A [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md>) with `cycles`, `notes`, `analytics` and `overallocations`. It has no `updates` and no `conflicts`. Its `baseline_id` is set only for `None` on a solved project with no unsolved edits.

## Errors

| Error | When |
|---|---|
| [`Error::Input`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>) | Supplied `data` fails validation |

## Example

Get the critical path of dates stored elsewhere, without scheduling them.

```rust
use plen_core::{
    AnalyticsOptions, AnalyzeOptions, DateTime, LinkData, LinkType, Project, ProjectData, TaskData,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let day = |d| DateTime::from_ymd_hm(2026, 1, d, 0, 0).ok_or("invalid date");

    let mut design = TaskData::new("design");
    design.start_date = Some(day(5)?);
    design.duration = Some(2.0);
    let mut build = TaskData::new("build");
    build.start_date = Some(day(7)?);
    build.duration = Some(3.0);
    let data = ProjectData {
        tasks: vec![design, build],
        links: vec![LinkData {
            id: "l1".into(),
            source: "design".into(),
            target: "build".into(),
            link_type: LinkType::Fs,
            lag: 0.0,
            lag_unit: None,
        }],
        ..Default::default()
    };

    let project = Project::default();
    let options = AnalyzeOptions {
        analytics: AnalyticsOptions {
            critical_path: true,
            slack: false,
        },
    };
    let result = project.analyze(Some(&data), &options)?;

    if let Some(critical) = result.analytics.as_ref().and_then(|a| a.critical_path.as_ref()) {
        println!("critical tasks: {:?}", critical.tasks);
    }
    Ok(())
}
```

## Related

- [`Project`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#analyze>) - the type and its other methods
- [`AnalyzeOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/analyze-options.md>) - which analytics to compute
- [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md>) - the returned result
- [Critical path and slack](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/critical-path-and-slack.md#analyzing-without-scheduling>) - analyzing supplied and current dates
