Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Provide outline tree #909

Open
Open
@alexheretic

Description

@alexheretic

We should provide textDocument/documentSymbol outlines that allow showing the symbols in a tree.

Pulled out my comment from #86 into it's own issue as I guess its a larger thing.

Current Status

atom-outline

textDocument/documentSymbol response
[{
  "name": "",
  "kind": 2,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 1,
        "character": 0
      },
      "end": {
        "line": 58,
        "character": 1
      }
    }
  },
  "containerName": null
}, {
  "name": "stuff",
  "kind": 2,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 7,
        "character": 4
      },
      "end": {
        "line": 7,
        "character": 9
      }
    }
  },
  "containerName": ""
}, {
  "name": "speaks",
  "kind": 2,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 8,
        "character": 8
      },
      "end": {
        "line": 8,
        "character": 14
      }
    }
  },
  "containerName": "stuff"
}, {
  "name": "Speaks",
  "kind": 11,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 9,
        "character": 18
      },
      "end": {
        "line": 9,
        "character": 24
      }
    }
  },
  "containerName": "speaks"
}, {
  "name": "speak",
  "kind": 6,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 10,
        "character": 15
      },
      "end": {
        "line": 10,
        "character": 20
      }
    }
  },
  "containerName": "Speaks"
}, {
  "name": "NUM_A",
  "kind": 14,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 14,
        "character": 10
      },
      "end": {
        "line": 14,
        "character": 15
      }
    }
  },
  "containerName": "stuff"
}, {
  "name": "Temp",
  "kind": 5,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 18,
        "character": 11
      },
      "end": {
        "line": 18,
        "character": 15
      }
    }
  },
  "containerName": "stuff"
}, {
  "name": "field",
  "kind": 8,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 19,
        "character": 8
      },
      "end": {
        "line": 19,
        "character": 13
      }
    }
  },
  "containerName": "Temp"
}, {
  "name": "Another",
  "kind": 5,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 21,
        "character": 11
      },
      "end": {
        "line": 21,
        "character": 18
      }
    }
  },
  "containerName": "stuff"
}, {
  "name": "AnEnum",
  "kind": 10,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 23,
        "character": 20
      },
      "end": {
        "line": 23,
        "character": 26
      }
    }
  },
  "containerName": "stuff"
}, {
  "name": "One",
  "kind": 8,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 24,
        "character": 8
      },
      "end": {
        "line": 24,
        "character": 11
      }
    }
  },
  "containerName": "AnEnum"
}, {
  "name": "Two",
  "kind": 8,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 25,
        "character": 8
      },
      "end": {
        "line": 25,
        "character": 11
      }
    }
  },
  "containerName": "AnEnum"
}, {
  "name": "name",
  "kind": 8,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 25,
        "character": 14
      },
      "end": {
        "line": 25,
        "character": 18
      }
    }
  },
  "containerName": "Two"
}, {
  "name": "Three",
  "kind": 8,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 26,
        "character": 8
      },
      "end": {
        "line": 26,
        "character": 13
      }
    }
  },
  "containerName": "AnEnum"
}, {
  "name": "something",
  "kind": 6,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 29,
        "character": 11
      },
      "end": {
        "line": 29,
        "character": 20
      }
    }
  },
  "containerName": null
}, {
  "name": "speak",
  "kind": 6,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 34,
        "character": 11
      },
      "end": {
        "line": 34,
        "character": 16
      }
    }
  },
  "containerName": "Speaks"
}, {
  "name": "self",
  "kind": 13,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 34,
        "character": 18
      },
      "end": {
        "line": 34,
        "character": 22
      }
    }
  },
  "containerName": null
}, {
  "name": "speak",
  "kind": 6,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 39,
        "character": 11
      },
      "end": {
        "line": 39,
        "character": 16
      }
    }
  },
  "containerName": "Speaks"
}, {
  "name": "self",
  "kind": 13,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 39,
        "character": 18
      },
      "end": {
        "line": 39,
        "character": 22
      }
    }
  },
  "containerName": null
}, {
  "name": "fun1",
  "kind": 12,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 43,
        "character": 7
      },
      "end": {
        "line": 43,
        "character": 11
      }
    }
  },
  "containerName": "stuff"
}, {
  "name": "fun2",
  "kind": 12,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 44,
        "character": 11
      },
      "end": {
        "line": 44,
        "character": 15
      }
    }
  },
  "containerName": null
}, {
  "name": "m",
  "kind": 13,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 50,
        "character": 16
      },
      "end": {
        "line": 50,
        "character": 17
      }
    }
  },
  "containerName": null
}, {
  "name": "main",
  "kind": 12,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 56,
        "character": 3
      },
      "end": {
        "line": 56,
        "character": 7
      }
    }
  },
  "containerName": ""
}, {
  "name": "a",
  "kind": 13,
  "location": {
    "uri": "file:///home/alex/project/rusttmp/src/main.rs",
    "range": {
      "start": {
        "line": 57,
        "character": 8
      },
      "end": {
        "line": 57,
        "character": 9
      }
    }
  },
  "containerName": null
}]

So we can see that we do already set containerName in a few cases. However, without nested location ranges atom can't construct the proper syntax tree outline & can't connect the containerName with the actual symbol name, so both appear separately.

So it looks like we should make the following improvements, that may need enhancements to rls-analysis:

  • Construct test case using above example.
  • Extend all location end positions to the end of the owning scope if applicable.
    So for example the mod stuff location should change from [7:4, 7:9] -> [7:4, 56:1]
  • Add missing symbols, ie impl Temp (probably just use Unknown to describe this symbol kind)
  • Add missing containerNames, ie fn fun1() { fn fun2() {} }
  • Once we have the symbol, rename impl Speaks for Temp "Speaks" -> "Speaks for Temp" (remove generics if they exist though?)
  • Make use of newer LSP symbol kinds struct, etc
  • Minor: Remove empty string name symbols & containerNames

Later enhancements:

  • Outlines for common macro declarations lazy_static!, thread_local!, etc
Test/example code
#![allow(unused)]
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;
use std::sync::Arc;

mod stuff {
    mod speaks {
        pub trait Speaks {
            fn speak(&self);
        }
    }
    use self::speaks::Speaks;
    const NUM_A: usize = 234;

    struct Temp {
        field: i32,
    }
    struct Another;

    pub(crate) enum AnEnum {
        One(u32, u32),
        Two { name: &'static str },
        Three,
    }
    impl Temp {
        fn something() -> i32 {
            1
        }
    }
    impl Speaks for Temp {
        fn speak(&self) {
            eprintln!("hello");
        }
    }
    impl Speaks for AnEnum {
        fn speak(&self) {
            eprintln!("hmmmm");
        }
    }
    fn fun1() {
        fn fun2() {}
    }
}

lazy_static! {
    pub static ref MAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(345, "345");
        m
    };
}

fn main() {
    let a = Arc::new(123);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions