Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

Commit

Permalink
Implement DocumentSymbolProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
ypresto committed Dec 30, 2016
1 parent c58853f commit f5f9ccb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
26 changes: 17 additions & 9 deletions locate/locate.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,29 @@ const fs = require('fs'),
path = require('path');
const _ = require('lodash');

function flatten(locateInfo, file, parentName) {
const DECLARATION_TYPES = ['class', 'module', 'method', 'classMethod'];

function flatten(locateInfo, file, parent) {
return _.flatMap(locateInfo, (symbols, type) => {
// TODO: return accessor or other types.
// TODO: parse include and inherit to find inherited symbols.
if (!_.includes(['module', 'class', 'method', 'classMethod'], type)) return [];
return _.flatMap(symbols, (children, name) => {
if (!_.includes(DECLARATION_TYPES, type)) {
// Skip top-level include or posn property etc.
return [];
}
return _.flatMap(symbols, (inner, name) => {
const sep = { method: '#', classMethod: '.' }[type] || '::';
const posn = children.posn || { line: 0, char: 0 };
const fullName = parentName ? `${parentName}${sep}${name}` : name;
const posn = inner.posn || { line: 0, char: 0 };
const fullName = parent ? `${parent.fullName}${sep}${name}` : name;
const symbolInfo = {
// TODO: parse names like 'ActiveRecord::Base'
name: name,
type: type,
file: file,
line: posn.line,
char: posn.char,
parent: parent,
fullName: fullName
};
return [symbolInfo].concat(flatten(children, file, fullName));
_.extend(symbolInfo, _.omit(inner, DECLARATION_TYPES));
return [symbolInfo].concat(flatten(inner, file, symbolInfo));
});
});
}
Expand All @@ -37,6 +42,9 @@ module.exports = class Locate {
// always: do this file now (if it's in the tree)
// add lookup hooks
}
listInFile(absPath) {
return _.clone(this.tree[absPath] || []);
}
find(name) {
// because our word pattern is designed to match symbols
// things like Gem::RequestSet may request a search for ':RequestSet'
Expand Down
25 changes: 24 additions & 1 deletion ruby.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use strict";
let vscode = require('vscode');
const vscode = require('vscode');
const { Location, Position, SymbolKind, SymbolInformation } = vscode;

let Locate = require('./locate/locate');
let cp = require('child_process');
Expand Down Expand Up @@ -177,6 +178,28 @@ function activate(context) {
}
};
subs.push(vscode.languages.registerDefinitionProvider(['ruby', 'erb'], defProvider));
const symbolKindTable = {
class: () => SymbolKind.Class,
module: () => SymbolKind.Module,
method: symbolInfo => symbolInfo.name === 'initialize' ? SymbolKind.Constructor : SymbolKind.Method,
classMethod: () => SymbolKind.Method,
};
const defaultSymbolKind = symbolInfo => {
console.warn(`Unknown symbol type: ${symbolInfo.type}`);
return SymbolKind.Variable;
};
const docSymbolProvider = {
provideDocumentSymbols: (document, token) => {
return locate.listInFile(document.fileName).map(match => {
const symbolKind = (symbolKindTable[match.type] || defaultSymbolKind)(match);
const parentName = match.parent ? match.parent.fullName : '';
const uri = vscode.Uri.file(match.file);
const location = new Location(uri, new Position(match.line, match.char));
return new SymbolInformation(match.name, symbolKind, parentName, location);
})
}
};
subs.push(vscode.languages.registerDocumentSymbolProvider(['ruby', 'erb'], docSymbolProvider));
}

subs.push(vscode.window.onDidChangeActiveTextEditor(balanceEvent));
Expand Down

0 comments on commit f5f9ccb

Please sign in to comment.