Merge pull request #2106 from Microsoft/addNavtoLimit

Add maxResultCount optional field to NavtoRequestArgs.  Change
This commit is contained in:
Steve Lucco
2015-02-23 11:57:16 -08:00
5 changed files with 107 additions and 52 deletions

View File

@@ -208,9 +208,9 @@ module ts.server {
return response.body[0];
}
getNavigateToItems(searchTerm: string): NavigateToItem[] {
getNavigateToItems(searchValue: string): NavigateToItem[] {
var args: protocol.NavtoRequestArgs = {
searchTerm,
searchValue,
file: this.host.getScriptFileNames()[0]
};

View File

@@ -65,6 +65,7 @@ module ts.server {
ls: ts.LanguageService = null;
compilationSettings: ts.CompilerOptions;
filenameToScript: ts.Map<ScriptInfo> = {};
roots: ScriptInfo[] = [];
constructor(public host: ServerHost, public project: Project) {
}
@@ -144,7 +145,7 @@ module ts.server {
var scriptInfo = ts.lookUp(this.filenameToScript, info.fileName);
if (!scriptInfo) {
this.filenameToScript[info.fileName] = info;
return info;
this.roots.push(info);
}
}
@@ -286,10 +287,12 @@ module ts.server {
return this.filenameToSourceFile[info.fileName];
}
getSourceFileFromName(filename: string) {
getSourceFileFromName(filename: string, requireOpen?: boolean) {
var info = this.projectService.getScriptInfo(filename);
if (info) {
return this.getSourceFile(info);
if ((!requireOpen) || info.isOpen) {
return this.getSourceFile(info);
}
}
}
@@ -324,7 +327,7 @@ module ts.server {
// add a root file to project
addRoot(info: ScriptInfo) {
info.defaultProject = this;
return this.compilerService.host.addRoot(info);
this.compilerService.host.addRoot(info);
}
filesToString() {
@@ -360,7 +363,7 @@ module ts.server {
}
interface ProjectServiceEventHandler {
(eventName: string, project: Project): void;
(eventName: string, project: Project, fileName: string): void;
}
export class ProjectService {
@@ -392,7 +395,6 @@ module ts.server {
}
}
log(msg: string, type = "Err") {
this.psLogger.msg(msg, type);
}
@@ -423,7 +425,20 @@ module ts.server {
for (var i = 0, len = referencingProjects.length; i < len; i++) {
referencingProjects[i].removeReferencedFile(info);
}
for (var j = 0, flen = this.openFileRoots.length; j < flen; j++) {
var openFile = this.openFileRoots[j];
if (this.eventHandler) {
this.eventHandler("context", openFile.defaultProject, openFile.fileName);
}
}
for (var j = 0, flen = this.openFilesReferenced.length; j < flen; j++) {
var openFile = this.openFilesReferenced[j];
if (this.eventHandler) {
this.eventHandler("context", openFile.defaultProject, openFile.fileName);
}
}
}
this.printProjects();
}
@@ -503,19 +518,52 @@ module ts.server {
info.close();
}
findReferencingProjects(info: ScriptInfo) {
findReferencingProjects(info: ScriptInfo, excludedProject?: Project) {
var referencingProjects: Project[] = [];
info.defaultProject = undefined;
for (var i = 0, len = this.inferredProjects.length; i < len; i++) {
this.inferredProjects[i].updateGraph();
if (this.inferredProjects[i].getSourceFile(info)) {
info.defaultProject = this.inferredProjects[i];
referencingProjects.push(this.inferredProjects[i]);
if (this.inferredProjects[i] != excludedProject) {
if (this.inferredProjects[i].getSourceFile(info)) {
info.defaultProject = this.inferredProjects[i];
referencingProjects.push(this.inferredProjects[i]);
}
}
}
return referencingProjects;
}
updateProjectStructure() {
this.log("updating project structure from ...", "Info");
this.printProjects();
for (var i = 0, len = this.openFilesReferenced.length; i < len; i++) {
var refdFile = this.openFilesReferenced[i];
refdFile.defaultProject.updateGraph();
var sourceFile = refdFile.defaultProject.getSourceFile(refdFile);
if (!sourceFile) {
this.openFilesReferenced = copyListRemovingItem(refdFile, this.openFilesReferenced);
this.addOpenFile(refdFile);
}
}
var openFileRoots: ScriptInfo[] = [];
for (var i = 0, len = this.openFileRoots.length; i < len; i++) {
var rootFile = this.openFileRoots[i];
var rootedProject = rootFile.defaultProject;
var referencingProjects = this.findReferencingProjects(rootFile, rootedProject);
if (referencingProjects.length == 0) {
rootFile.defaultProject = rootedProject;
openFileRoots.push(rootFile);
}
else {
// remove project from inferred projects list
this.inferredProjects = copyListRemovingItem(rootedProject, this.inferredProjects);
this.openFilesReferenced.push(rootFile);
}
}
this.openFileRoots = openFileRoots;
this.printProjects();
}
getScriptInfo(filename: string) {
filename = ts.normalizePath(filename);
return ts.lookUp(this.filenameToScriptInfo, filename);
@@ -621,6 +669,7 @@ module ts.server {
this.psLogger.startGroup();
for (var i = 0, len = this.inferredProjects.length; i < len; i++) {
var project = this.inferredProjects[i];
project.updateGraph();
this.psLogger.info("Project " + i.toString());
this.psLogger.info(project.filesToString());
this.psLogger.info("-----------------------------------------------");

View File

@@ -676,7 +676,11 @@ declare module ts.server.protocol {
* Search term to navigate to from current location; term can
* be '.*' or an identifier prefix.
*/
searchTerm: string;
searchValue: string;
/**
* Optional limit on the number of items to return.
*/
maxResultCount?: number;
}
/**

View File

@@ -82,7 +82,6 @@ module ts.server {
private watchedFiles: WatchedFile[] = [];
private nextFileToCheck = 0;
private watchTimer: NodeJS.Timer;
private static fileDeleted = 34;
// average async stat takes about 30 microseconds
// set chunk size to do 30 files in < 1 millisecond
@@ -111,13 +110,7 @@ module ts.server {
fs.stat(watchedFile.fileName,(err, stats) => {
if (err) {
var msg = err.message;
if (err.errno) {
msg += " errno: " + err.errno.toString();
}
if (err.errno == WatchedFileSet.fileDeleted) {
watchedFile.callback(watchedFile.fileName);
}
watchedFile.callback(watchedFile.fileName);
}
else if (watchedFile.mtime.getTime() != stats.mtime.getTime()) {
watchedFile.mtime = WatchedFileSet.getModifiedTime(watchedFile.fileName);

View File

@@ -52,30 +52,6 @@ module ts.server {
return 1;
}
}
function sortNavItems(items: ts.NavigateToItem[]) {
return items.sort((a, b) => {
if (a.matchKind < b.matchKind) {
return -1;
}
else if (a.matchKind == b.matchKind) {
var lowa = a.name.toLowerCase();
var lowb = b.name.toLowerCase();
if (lowa < lowb) {
return -1;
}
else if (lowa == lowb) {
return 0;
}
else {
return 1;
}
}
else {
return 1;
}
})
}
function formatDiag(fileName: string, project: Project, diag: ts.Diagnostic) {
return {
@@ -138,7 +114,18 @@ module ts.server {
changeSeq = 0;
constructor(private host: ServerHost, private logger: Logger) {
this.projectService = new ProjectService(host, logger);
this.projectService =
new ProjectService(host, logger, (eventName,project,fileName) => {
this.handleEvent(eventName, project, fileName);
});
}
handleEvent(eventName: string, project: Project, fileName: string) {
if (eventName == "context") {
this.projectService.log("got context event, updating diagnostics for" + fileName, "Info");
this.updateErrorCheck([{ fileName, project }], this.changeSeq,
(n) => n == this.changeSeq, 100);
}
}
logError(err: Error, cmd: string) {
@@ -215,6 +202,14 @@ module ts.server {
this.semanticCheck(file, project);
}
updateProjectStructure(seq: number, matchSeq: (seq: number) => boolean, ms = 1500) {
setTimeout(() => {
if (matchSeq(seq)) {
this.projectService.updateProjectStructure();
}
}, ms);
}
updateErrorCheck(checkList: PendingErrorCheck[], seq: number,
matchSeq: (seq: number) => boolean, ms = 1500, followMs = 200) {
if (followMs > ms) {
@@ -231,7 +226,7 @@ module ts.server {
var checkOne = () => {
if (matchSeq(seq)) {
var checkSpec = checkList[index++];
if (checkSpec.project.getSourceFileFromName(checkSpec.fileName)) {
if (checkSpec.project.getSourceFileFromName(checkSpec.fileName, true)) {
this.syntacticCheck(checkSpec.fileName, checkSpec.project);
this.immediateId = setImmediate(() => {
this.semanticCheck(checkSpec.fileName, checkSpec.project);
@@ -404,7 +399,7 @@ module ts.server {
var position = compilerService.host.lineColToPosition(file, line, col);
var quickInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
if (!quickInfo) {
throw Errors.NoContent;
return undefined;
}
var displayString = ts.displayPartsToString(quickInfo.displayParts);
@@ -494,7 +489,7 @@ module ts.server {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
if (!project) {
throw Errors.NoProject;
return undefined;
}
var compilerService = project.compilerService;
@@ -559,6 +554,10 @@ module ts.server {
compilerService.host.editScript(file, start, end, insertString);
this.changeSeq++;
}
// update project structure on idle commented out
// until we can have the host return only the root files
// from getScriptFileNames()
//this.updateProjectStructure(this.changeSeq, (n) => n == this.changeSeq);
}
}
@@ -625,7 +624,7 @@ module ts.server {
return this.decorateNavigationBarItem(project, fileName, items);
}
getNavigateToItems(searchTerm: string, fileName: string): protocol.NavtoItem[] {
getNavigateToItems(searchValue: string, fileName: string, maxResultCount?: number): protocol.NavtoItem[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
if (!project) {
@@ -633,7 +632,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var navItems = sortNavItems(compilerService.languageService.getNavigateToItems(searchTerm));
var navItems = compilerService.languageService.getNavigateToItems(searchValue, maxResultCount);
if (!navItems) {
throw Errors.NoContent;
}
@@ -690,6 +689,7 @@ module ts.server {
try {
var request = <protocol.Request>JSON.parse(message);
var response: any;
var errorMessage: string;
switch (request.command) {
case CommandNames.Definition: {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
@@ -714,6 +714,9 @@ module ts.server {
case CommandNames.Quickinfo: {
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.col, quickinfoArgs.file);
if (!response) {
errorMessage = "No info at this location";
}
break;
}
case CommandNames.Format: {
@@ -729,6 +732,9 @@ module ts.server {
case CommandNames.Completions: {
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
response = this.getCompletions(request.arguments.line, request.arguments.col, completionsArgs.prefix, request.arguments.file);
if (!response) {
errorMessage = "No completions at this location";
}
break;
}
case CommandNames.CompletionDetails: {
@@ -765,7 +771,7 @@ module ts.server {
}
case CommandNames.Navto: {
var navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
response = this.getNavigateToItems(navtoArgs.searchTerm, navtoArgs.file);
response = this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount);
break;
}
case CommandNames.Brace: {
@@ -788,6 +794,9 @@ module ts.server {
if (response) {
this.output(response, request.command, request.seq);
}
else if (errorMessage) {
this.output(undefined, request.command, request.seq, errorMessage);
}
} catch (err) {
if (err instanceof OperationCanceledException) {