graphql-language-service
Advanced tools
Comparing version 0.0.9 to 0.0.10
{ | ||
"name": "graphql-language-service", | ||
"repository": "https://github.com/graphql/graphql-language-service", | ||
"version": "0.0.9", | ||
"version": "0.0.10", | ||
"description": "An interface for building GraphQL language services for IDEs", | ||
@@ -42,13 +42,14 @@ "contributors": [ | ||
"babel-polyfill": "6.16.0", | ||
"fb-watchman": "^2.0.0", | ||
"graphql": "^0.9.2", | ||
"graphql-language-service-config": "0.0.7", | ||
"graphql-language-service-interface": "0.0.7", | ||
"graphql-language-service-server": "0.0.10", | ||
"graphql-language-service-parser": "0.0.6", | ||
"graphql-language-service-server": "0.0.11", | ||
"graphql-language-service-types": "0.0.12", | ||
"graphql-language-service-utils": "0.0.6", | ||
"yargs": "^7.0.1", | ||
"graphql-language-service-types": "0.0.12", | ||
"graphql-language-service-config": "0.0.7", | ||
"graphql-language-service-parser": "0.0.6", | ||
"fb-watchman": "^2.0.0", | ||
"nullthrows": "^1.0.0", | ||
"vscode-jsonrpc": "^3.2.0" | ||
"vscode-jsonrpc": "^3.2.0", | ||
"vscode-languageserver": "^3.2.0", | ||
"yargs": "^7.0.1" | ||
}, | ||
@@ -55,0 +56,0 @@ "devDependencies": { |
@@ -6,17 +6,11 @@ 'use strict'; | ||
}); | ||
exports.handleDidOpenOrSaveNotification = handleDidOpenOrSaveNotification; | ||
exports.handleDidChangeNotification = handleDidChangeNotification; | ||
exports.handleDidCloseNotification = handleDidCloseNotification; | ||
exports.handleInitializeRequest = handleInitializeRequest; | ||
exports.handleCompletionRequest = handleCompletionRequest; | ||
exports.handleDefinitionRequest = handleDefinitionRequest; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** | ||
* Copyright (c) Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* | ||
*/ | ||
var _vscodeLanguageserver = require('vscode-languageserver'); | ||
exports.processIPCNotificationMessage = processIPCNotificationMessage; | ||
exports.processIPCRequestMessage = processIPCRequestMessage; | ||
exports.processStreamMessage = processStreamMessage; | ||
var _graphqlLanguageServiceConfig = require('graphql-language-service-config'); | ||
@@ -32,2 +26,4 @@ | ||
var _vscodeJsonrpc = require('vscode-jsonrpc'); | ||
var _GraphQLCache = require('./GraphQLCache'); | ||
@@ -37,17 +33,12 @@ | ||
// Response message error codes | ||
var ERROR_CODES = { | ||
PARSE_ERROR: -32700, | ||
INVALID_REQUEST: -32600, | ||
METHOD_NOT_FOUND: -32601, | ||
INVALID_PARAMS: -32602, | ||
INTERNAL_ERROR: -32603, | ||
SERVER_ERROR_START: -32099, | ||
SERVER_ERROR_END: -32000, | ||
SERVER_NOT_INITIALIZED: -32002, | ||
UNKNOWN_ERROR_CODE: -32001 | ||
}; | ||
/** | ||
* Copyright (c) Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* | ||
*/ | ||
var REQUEST_IDS_IN_PROGRESS = []; | ||
var graphQLCache = void 0; | ||
@@ -57,26 +48,17 @@ var languageService = void 0; | ||
function processIPCNotificationMessage(message, writer) { | ||
var method, response, textDocument, diagnostics, uri, text, cachedDocument, contentChanges, documentUri; | ||
return regeneratorRuntime.async(function processIPCNotificationMessage$(_context) { | ||
function handleDidOpenOrSaveNotification(params) { | ||
var textDocument, uri, text, cachedDocument, diagnostics; | ||
return regeneratorRuntime.async(function handleDidOpenOrSaveNotification$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
method = message.method; | ||
response = void 0; | ||
textDocument = void 0; | ||
diagnostics = void 0; | ||
_context.t0 = method; | ||
_context.next = _context.t0 === 'textDocument/didOpen' ? 7 : _context.t0 === 'textDocument/didSave' ? 7 : _context.t0 === 'textDocument/didChange' ? 19 : _context.t0 === 'textDocument/didClose' ? 31 : _context.t0 === 'exit' ? 36 : 38; | ||
break; | ||
case 7: | ||
if (!(!message.params || !message.params.textDocument)) { | ||
_context.next = 9; | ||
if (!(!params || !params.textDocument)) { | ||
_context.next = 2; | ||
break; | ||
} | ||
return _context.abrupt('return'); | ||
throw new Error('`textDocument` argument is required.'); | ||
case 9: | ||
textDocument = message.params.textDocument; | ||
case 2: | ||
textDocument = params.textDocument; | ||
uri = textDocument.uri; | ||
@@ -100,72 +82,61 @@ text = textDocument.text; | ||
_context.next = 15; | ||
_context.next = 8; | ||
return regeneratorRuntime.awrap(provideDiagnosticsMessage(text, uri)); | ||
case 15: | ||
case 8: | ||
diagnostics = _context.sent; | ||
return _context.abrupt('return', { uri: uri, diagnostics: diagnostics }); | ||
response = convertToRpcMessage({ | ||
method: 'textDocument/publishDiagnostics', | ||
params: { uri: uri, diagnostics: diagnostics } | ||
}); | ||
sendMessageIPC(response, writer); | ||
return _context.abrupt('break', 38); | ||
case 10: | ||
case 'end': | ||
return _context.stop(); | ||
} | ||
} | ||
}, null, this); | ||
} | ||
case 19: | ||
if (!(!message.params || !message.params.textDocument || !message.params.contentChanges)) { | ||
_context.next = 21; | ||
function handleDidChangeNotification(params) { | ||
var textDocument, contentChanges, documentUri, cachedDocument, diagnostics; | ||
return regeneratorRuntime.async(function handleDidChangeNotification$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
if (!(!params || !params.textDocument || !params.contentChanges)) { | ||
_context2.next = 2; | ||
break; | ||
} | ||
return _context.abrupt('return'); | ||
throw new Error('`textDocument` and `contentChanges` arguments are required.'); | ||
case 21: | ||
case 2: | ||
textDocument = params.textDocument; | ||
contentChanges = params.contentChanges; | ||
textDocument = message.params.textDocument; | ||
contentChanges = message.params.contentChanges; | ||
// As `contentChanges` is an array and we just want the | ||
// latest update to the text, grab the last entry from the array. | ||
documentUri = textDocument.uri || message.params.uri; | ||
documentUri = textDocument.uri || params.uri; | ||
invalidateCache(textDocument, documentUri, contentChanges[contentChanges.length - 1]); | ||
// Send the diagnostics onChange as well | ||
_context.next = 27; | ||
return regeneratorRuntime.awrap(provideDiagnosticsMessage(textDocumentCache.get(documentUri), documentUri)); | ||
cachedDocument = textDocumentCache.get(documentUri); | ||
case 27: | ||
diagnostics = _context.sent; | ||
response = convertToRpcMessage({ | ||
method: 'textDocument/publishDiagnostics', | ||
params: { documentUri: documentUri, diagnostics: diagnostics } | ||
}); | ||
sendMessageIPC(response, writer); | ||
return _context.abrupt('break', 38); | ||
case 31: | ||
if (!(!message.params || !message.params.textDocument)) { | ||
_context.next = 33; | ||
if (cachedDocument) { | ||
_context2.next = 9; | ||
break; | ||
} | ||
return _context.abrupt('return'); | ||
return _context2.abrupt('return'); | ||
case 33: | ||
textDocument = message.params.textDocument; | ||
case 9: | ||
_context2.next = 11; | ||
return regeneratorRuntime.awrap(provideDiagnosticsMessage(cachedDocument.content.text, documentUri)); | ||
if (textDocumentCache.has(textDocument.uri)) { | ||
textDocumentCache.delete(textDocument.uri); | ||
} | ||
return _context.abrupt('break', 38); | ||
case 11: | ||
diagnostics = _context2.sent; | ||
return _context2.abrupt('return', { documentUri: documentUri, diagnostics: diagnostics }); | ||
case 36: | ||
process.exit(0); | ||
return _context.abrupt('break', 38); | ||
case 38: | ||
case 13: | ||
case 'end': | ||
return _context.stop(); | ||
return _context2.stop(); | ||
} | ||
@@ -176,156 +147,106 @@ } | ||
function processIPCRequestMessage(message, configDir, writer) { | ||
var method, response, textDocument, cachedDocument, query, result, serverCapabilities, position, pos, formatted, requestIDToCancel, index; | ||
return regeneratorRuntime.async(function processIPCRequestMessage$(_context2) { | ||
function handleDidCloseNotification(params) { | ||
var textDocument; | ||
return regeneratorRuntime.async(function handleDidCloseNotification$(_context3) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
method = message.method; | ||
response = void 0; | ||
textDocument = void 0; | ||
cachedDocument = void 0; | ||
query = void 0; | ||
result = void 0; | ||
_context2.t0 = method; | ||
_context2.next = _context2.t0 === 'initialize' ? 9 : _context2.t0 === 'textDocument/completion' ? 17 : _context2.t0 === 'textDocument/definition' ? 30 : _context2.t0 === '$/cancelRequest' ? 44 : _context2.t0 === 'shutdown' ? 50 : 51; | ||
break; | ||
case 9: | ||
if (!(!message.params || !message.params.rootPath)) { | ||
_context2.next = 11; | ||
if (!(!params || !params.textDocument)) { | ||
_context3.next = 2; | ||
break; | ||
} | ||
return _context2.abrupt('return'); | ||
throw new Error('`textDocument` is required.'); | ||
case 11: | ||
_context2.next = 13; | ||
return regeneratorRuntime.awrap(initialize(configDir ? configDir.trim() : message.params.rootPath)); | ||
case 2: | ||
textDocument = params.textDocument; | ||
case 13: | ||
serverCapabilities = _context2.sent; | ||
if (serverCapabilities === null) { | ||
response = convertToRpcMessage({ | ||
id: '-1', | ||
error: { | ||
code: ERROR_CODES.SERVER_NOT_INITIALIZED, | ||
message: '.graphqlrc not found' | ||
} | ||
}); | ||
} else { | ||
response = convertToRpcMessage({ | ||
id: message.id, | ||
result: serverCapabilities | ||
}); | ||
if (textDocumentCache.has(textDocument.uri)) { | ||
textDocumentCache.delete(textDocument.uri); | ||
} | ||
sendMessageIPC(response, writer); | ||
return _context2.abrupt('break', 51); | ||
case 17: | ||
if (!(!message.params || !message.params.textDocument || !message.params.position)) { | ||
_context2.next = 19; | ||
case 4: | ||
case 'end': | ||
return _context3.stop(); | ||
} | ||
} | ||
}, null, this); | ||
} | ||
function handleInitializeRequest(params, token, configDir) { | ||
var serverCapabilities; | ||
return regeneratorRuntime.async(function handleInitializeRequest$(_context4) { | ||
while (1) { | ||
switch (_context4.prev = _context4.next) { | ||
case 0: | ||
if (!(!params || !params.rootPath)) { | ||
_context4.next = 2; | ||
break; | ||
} | ||
return _context2.abrupt('return'); | ||
throw new Error('`rootPath` argument is required.'); | ||
case 19: | ||
textDocument = message.params.textDocument; | ||
position = message.params.position; | ||
case 2: | ||
_context4.next = 4; | ||
return regeneratorRuntime.awrap(initialize(configDir ? configDir.trim() : params.rootPath)); | ||
case 4: | ||
serverCapabilities = _context4.sent; | ||
cachedDocument = getCachedDocument(textDocument.uri); | ||
if (cachedDocument) { | ||
_context2.next = 24; | ||
if (serverCapabilities) { | ||
_context4.next = 7; | ||
break; | ||
} | ||
return _context2.abrupt('return'); | ||
throw new Error('GraphQL Language Server is not initialized.'); | ||
case 24: | ||
case 7: | ||
return _context4.abrupt('return', serverCapabilities); | ||
query = cachedDocument.content.text; | ||
_context2.next = 27; | ||
return regeneratorRuntime.awrap(languageService.getAutocompleteSuggestions(query, position, textDocument.uri)); | ||
case 8: | ||
case 'end': | ||
return _context4.stop(); | ||
} | ||
} | ||
}, null, this); | ||
} | ||
case 27: | ||
result = _context2.sent; | ||
sendMessageIPC(convertToRpcMessage({ | ||
id: message.id, | ||
result: { items: result, isCompleted: true } | ||
}), writer); | ||
return _context2.abrupt('break', 51); | ||
case 30: | ||
if (!(!message.params || !message.params.textDocument || !message.params.position)) { | ||
_context2.next = 32; | ||
function handleCompletionRequest(params, token) { | ||
var textDocument, position, cachedDocument, query, result; | ||
return regeneratorRuntime.async(function handleCompletionRequest$(_context5) { | ||
while (1) { | ||
switch (_context5.prev = _context5.next) { | ||
case 0: | ||
if (!(!params || !params.textDocument || !params.position)) { | ||
_context5.next = 2; | ||
break; | ||
} | ||
return _context2.abrupt('return'); | ||
throw new Error('`textDocument` argument is required.'); | ||
case 32: | ||
textDocument = message.params.textDocument; | ||
pos = message.params.position; | ||
case 2: | ||
textDocument = params.textDocument; | ||
position = params.position; | ||
cachedDocument = getCachedDocument(textDocument.uri); | ||
if (cachedDocument) { | ||
_context2.next = 37; | ||
_context5.next = 7; | ||
break; | ||
} | ||
return _context2.abrupt('return'); | ||
throw new Error(textDocument.uri + ' is not available.'); | ||
case 37: | ||
case 7: | ||
query = cachedDocument.content.text; | ||
_context2.next = 40; | ||
return regeneratorRuntime.awrap(languageService.getDefinition(query, pos, textDocument.uri)); | ||
_context5.next = 10; | ||
return regeneratorRuntime.awrap(languageService.getAutocompleteSuggestions(query, position, textDocument.uri)); | ||
case 40: | ||
result = _context2.sent; | ||
formatted = result ? result.definitions.map(function (res) { | ||
return { | ||
uri: _path2.default.join('file://', res.path), | ||
range: res.range | ||
}; | ||
}) : []; | ||
case 10: | ||
result = _context5.sent; | ||
return _context5.abrupt('return', { items: result, isIncomplete: false }); | ||
sendMessageIPC(convertToRpcMessage({ | ||
id: message.id, | ||
result: formatted | ||
}), writer); | ||
return _context2.abrupt('break', 51); | ||
case 44: | ||
if (!(!message.params || !message.params.id)) { | ||
_context2.next = 46; | ||
break; | ||
} | ||
return _context2.abrupt('return'); | ||
case 46: | ||
requestIDToCancel = message.params.id; | ||
index = REQUEST_IDS_IN_PROGRESS.indexOf(requestIDToCancel); | ||
if (index !== -1) { | ||
REQUEST_IDS_IN_PROGRESS.splice(index, 1); | ||
// A cancelled request still needs to send an empty response back | ||
sendMessageIPC({ id: requestIDToCancel }, writer); | ||
} | ||
return _context2.abrupt('break', 51); | ||
case 50: | ||
return _context2.abrupt('break', 51); | ||
case 51: | ||
case 12: | ||
case 'end': | ||
return _context2.stop(); | ||
return _context5.stop(); | ||
} | ||
@@ -336,155 +257,54 @@ } | ||
function processStreamMessage(message, configDir) { | ||
var graphQLConfigDir, json, id, method, result, responseMsg, _json$args, query, filePath, position, formatted; | ||
return regeneratorRuntime.async(function processStreamMessage$(_context3) { | ||
function handleDefinitionRequest(params, token) { | ||
var textDocument, pos, cachedDocument, query, result, formatted; | ||
return regeneratorRuntime.async(function handleDefinitionRequest$(_context6) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
switch (_context6.prev = _context6.next) { | ||
case 0: | ||
if (!(message.length === 0)) { | ||
_context3.next = 2; | ||
if (!(!params || !params.textDocument || !params.position)) { | ||
_context6.next = 2; | ||
break; | ||
} | ||
return _context3.abrupt('return'); | ||
throw new Error('`textDocument` and `position` arguments are required.'); | ||
case 2: | ||
if (graphQLCache) { | ||
_context3.next = 10; | ||
break; | ||
} | ||
textDocument = params.textDocument; | ||
pos = params.position; | ||
cachedDocument = getCachedDocument(textDocument.uri); | ||
graphQLConfigDir = (0, _graphqlLanguageServiceConfig.findGraphQLConfigDir)(configDir ? configDir.trim() : process.cwd()); | ||
if (graphQLConfigDir) { | ||
_context3.next = 7; | ||
if (cachedDocument) { | ||
_context6.next = 7; | ||
break; | ||
} | ||
process.stdout.write(JSON.stringify(convertToRpcMessage({ | ||
id: '-1', | ||
error: { | ||
code: ERROR_CODES.SERVER_NOT_INITIALIZED, | ||
message: '.graphqlrc not found' | ||
} | ||
}))); | ||
return _context3.abrupt('return'); | ||
throw new Error(textDocument.uri + ' is not available.'); | ||
case 7: | ||
_context3.next = 9; | ||
return regeneratorRuntime.awrap((0, _GraphQLCache.getGraphQLCache)(graphQLConfigDir)); | ||
query = cachedDocument.content.text; | ||
_context6.next = 10; | ||
return regeneratorRuntime.awrap(languageService.getDefinition(query, pos, textDocument.uri)); | ||
case 9: | ||
graphQLCache = _context3.sent; | ||
case 10: | ||
if (!languageService) { | ||
languageService = new _graphqlLanguageServiceInterface.GraphQLLanguageService(graphQLCache); | ||
} | ||
json = void 0; | ||
_context3.prev = 12; | ||
json = JSON.parse(message); | ||
_context3.next = 20; | ||
break; | ||
case 16: | ||
_context3.prev = 16; | ||
_context3.t0 = _context3['catch'](12); | ||
process.stdout.write(JSON.stringify(convertToRpcMessage({ | ||
id: '-1', | ||
error: { | ||
code: ERROR_CODES.PARSE_ERROR, | ||
message: 'Request contains incorrect JSON format' | ||
} | ||
}))); | ||
return _context3.abrupt('return'); | ||
case 20: | ||
id = json.id; | ||
method = json.method; | ||
result = null; | ||
responseMsg = null; | ||
_json$args = json.args, query = _json$args.query, filePath = _json$args.filePath, position = _json$args.position; | ||
_context3.t1 = method; | ||
_context3.next = _context3.t1 === 'disconnect' ? 28 : _context3.t1 === 'getDiagnostics' ? 30 : _context3.t1 === 'getDefinition' ? 36 : _context3.t1 === 'getAutocompleteSuggestions' ? 42 : _context3.t1 === 'getOutline' ? 49 : 53; | ||
break; | ||
case 28: | ||
process.exit(0); | ||
return _context3.abrupt('break', 54); | ||
case 30: | ||
_context3.next = 32; | ||
return regeneratorRuntime.awrap(provideDiagnosticsMessage(query, filePath)); | ||
case 32: | ||
result = _context3.sent; | ||
responseMsg = convertToRpcMessage({ | ||
type: 'response', | ||
id: id, | ||
result: result | ||
}); | ||
process.stdout.write(JSON.stringify(responseMsg) + '\n'); | ||
return _context3.abrupt('break', 54); | ||
case 36: | ||
_context3.next = 38; | ||
return regeneratorRuntime.awrap(languageService.getDefinition(query, position, filePath)); | ||
case 38: | ||
result = _context3.sent; | ||
responseMsg = convertToRpcMessage({ | ||
type: 'response', | ||
id: id, | ||
result: result | ||
}); | ||
process.stdout.write(JSON.stringify(responseMsg) + '\n'); | ||
return _context3.abrupt('break', 54); | ||
case 42: | ||
_context3.next = 44; | ||
return regeneratorRuntime.awrap(languageService.getAutocompleteSuggestions(query, position, filePath)); | ||
case 44: | ||
result = _context3.sent; | ||
formatted = result.map(function (res) { | ||
result = _context6.sent; | ||
formatted = result ? result.definitions.map(function (res) { | ||
return { | ||
text: res.label, | ||
typeName: res.detail ? String(res.detail) : null, | ||
description: res.documentation || null | ||
// TODO: fix this hack! | ||
// URI is being misused all over this library - there's a link that | ||
// defines how an URI should be structured: | ||
// https://tools.ietf.org/html/rfc3986 | ||
// Remove the below hack once the usage of URI is sorted out in related | ||
// libraries. | ||
uri: res.path.indexOf('file:') === 0 ? res.path : _path2.default.join('file:', res.path), | ||
range: res.range | ||
}; | ||
}); | ||
}) : []; | ||
return _context6.abrupt('return', formatted); | ||
responseMsg = convertToRpcMessage({ | ||
type: 'response', | ||
id: id, | ||
formatted: formatted | ||
}); | ||
process.stdout.write(JSON.stringify(responseMsg) + '\n'); | ||
return _context3.abrupt('break', 54); | ||
case 49: | ||
result = (0, _graphqlLanguageServiceInterface.getOutline)(query); | ||
responseMsg = convertToRpcMessage({ | ||
type: 'response', | ||
id: id, | ||
result: result | ||
}); | ||
process.stdout.write(JSON.stringify(responseMsg) + '\n'); | ||
return _context3.abrupt('break', 54); | ||
case 53: | ||
return _context3.abrupt('break', 54); | ||
case 54: | ||
case 13: | ||
case 'end': | ||
return _context3.stop(); | ||
return _context6.stop(); | ||
} | ||
} | ||
}, null, this, [[12, 16]]); | ||
}, null, this); | ||
} | ||
@@ -498,5 +318,5 @@ | ||
var serverCapabilities, configDir; | ||
return regeneratorRuntime.async(function initialize$(_context4) { | ||
return regeneratorRuntime.async(function initialize$(_context7) { | ||
while (1) { | ||
switch (_context4.prev = _context4.next) { | ||
switch (_context7.prev = _context7.next) { | ||
case 0: | ||
@@ -513,22 +333,22 @@ serverCapabilities = { | ||
if (configDir) { | ||
_context4.next = 4; | ||
_context7.next = 4; | ||
break; | ||
} | ||
return _context4.abrupt('return', null); | ||
return _context7.abrupt('return', null); | ||
case 4: | ||
_context4.next = 6; | ||
_context7.next = 6; | ||
return regeneratorRuntime.awrap((0, _GraphQLCache.getGraphQLCache)(configDir)); | ||
case 6: | ||
graphQLCache = _context4.sent; | ||
graphQLCache = _context7.sent; | ||
languageService = new _graphqlLanguageServiceInterface.GraphQLLanguageService(graphQLCache); | ||
return _context4.abrupt('return', serverCapabilities); | ||
return _context7.abrupt('return', serverCapabilities); | ||
case 9: | ||
case 'end': | ||
return _context4.stop(); | ||
return _context7.stop(); | ||
} | ||
@@ -541,11 +361,11 @@ } | ||
var results, queryLines, totalLines, lastLineLength, lastCharacterPosition; | ||
return regeneratorRuntime.async(function provideDiagnosticsMessage$(_context5) { | ||
return regeneratorRuntime.async(function provideDiagnosticsMessage$(_context8) { | ||
while (1) { | ||
switch (_context5.prev = _context5.next) { | ||
switch (_context8.prev = _context8.next) { | ||
case 0: | ||
_context5.next = 2; | ||
_context8.next = 2; | ||
return regeneratorRuntime.awrap(languageService.getDiagnostics(query, uri)); | ||
case 2: | ||
results = _context5.sent; | ||
results = _context8.sent; | ||
@@ -563,7 +383,7 @@ if (results && results.length > 0) { | ||
return _context5.abrupt('return', results); | ||
return _context8.abrupt('return', results); | ||
case 5: | ||
case 'end': | ||
return _context5.stop(); | ||
return _context8.stop(); | ||
} | ||
@@ -574,18 +394,2 @@ } | ||
function sendMessageIPC(message, writer) { | ||
writer.write(message); | ||
} | ||
/** | ||
* Composes a language server protocol JSON message. | ||
*/ | ||
function convertToRpcMessage(metaMessage) { | ||
var message = _extends({ | ||
jsonrpc: '2.0', | ||
protocol: 'graphql_language_service' | ||
}, metaMessage); | ||
return message; | ||
} | ||
function invalidateCache(textDocument, uri, content) { | ||
@@ -592,0 +396,0 @@ if (!uri) { |
@@ -15,6 +15,19 @@ 'use strict'; | ||
var _vscodeLanguageserver = require('vscode-languageserver'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Copyright (c) Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* | ||
*/ | ||
exports.default = function startServer(options) { | ||
var configDir; | ||
var configDir, reader, writer, _port, socket, connection; | ||
return regeneratorRuntime.async(function startServer$(_context) { | ||
@@ -24,31 +37,75 @@ while (1) { | ||
case 0: | ||
if (!options || !options.configDir) { | ||
process.stderr.write('--configDir is required!'); | ||
process.exit(1); | ||
if (options) { | ||
_context.next = 4; | ||
break; | ||
} | ||
process.stderr.write('At least --configDir option is required.'); | ||
process.exit(1); | ||
return _context.abrupt('return'); | ||
case 4: | ||
if (options.configDir) { | ||
_context.next = 8; | ||
break; | ||
} | ||
process.stderr.write('--configDir is required.'); | ||
process.exit(1); | ||
return _context.abrupt('return'); | ||
case 8: | ||
configDir = options.configDir; | ||
if (!(options && options.method)) { | ||
_context.next = 12; | ||
_context.next = 31; | ||
break; | ||
} | ||
reader = void 0; | ||
writer = void 0; | ||
_context.t0 = options.method; | ||
_context.next = _context.t0 === 'stream' ? 6 : _context.t0 === 'socket' ? 8 : _context.t0 === 'node' ? 10 : 10; | ||
_context.next = _context.t0 === 'stream' ? 15 : _context.t0 === 'socket' ? 18 : _context.t0 === 'node' ? 25 : 25; | ||
break; | ||
case 6: | ||
connectWithStream(configDir); | ||
return _context.abrupt('break', 12); | ||
case 15: | ||
reader = new _vscodeJsonrpc.StreamMessageReader(process.stdin); | ||
writer = new _vscodeJsonrpc.StreamMessageWriter(process.stdout); | ||
return _context.abrupt('break', 28); | ||
case 8: | ||
connectWithSocket(configDir, options.port); | ||
return _context.abrupt('break', 12); | ||
case 18: | ||
if (options.port) { | ||
_context.next = 22; | ||
break; | ||
} | ||
case 10: | ||
connectWithNodeIPC(configDir); | ||
return _context.abrupt('break', 12); | ||
process.stderr.write('--port is required to establish socket connection.'); | ||
process.exit(1); | ||
return _context.abrupt('return'); | ||
case 12: | ||
case 22: | ||
_port = options.port; | ||
socket = _net2.default.createServer(function (client) { | ||
client.setEncoding('utf8'); | ||
reader = new _vscodeJsonrpc.SocketMessageReader(client); | ||
writer = new _vscodeJsonrpc.SocketMessageWriter(client); | ||
client.on('end', function () { | ||
socket.close(); | ||
process.exit(0); | ||
}); | ||
}).listen(_port); | ||
return _context.abrupt('break', 28); | ||
case 25: | ||
reader = new _vscodeJsonrpc.IPCMessageReader(process); | ||
writer = new _vscodeJsonrpc.IPCMessageWriter(process); | ||
return _context.abrupt('break', 28); | ||
case 28: | ||
connection = (0, _vscodeJsonrpc.createMessageConnection)(reader, writer); | ||
addHandlers(connection, configDir); | ||
connection.listen(); | ||
case 31: | ||
case 'end': | ||
@@ -59,86 +116,93 @@ return _context.stop(); | ||
}, null, this); | ||
}; /** | ||
* Copyright (c) Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* | ||
*/ | ||
}; | ||
function connectWithSocket(configDir, port) { | ||
var socket = _net2.default.createServer(function (client) { | ||
client.setEncoding('utf8'); | ||
var messageReader = new _vscodeJsonrpc.SocketMessageReader(client); | ||
var messageWriter = new _vscodeJsonrpc.SocketMessageWriter(client); | ||
function addHandlers(connection, configDir) { | ||
var _this = this; | ||
client.on('end', function () { | ||
socket.close(); | ||
process.exit(0); | ||
}); | ||
connection.onNotification(_vscodeLanguageserver.DidOpenTextDocumentNotification.type, function _callee(params) { | ||
var diagnostics; | ||
return regeneratorRuntime.async(function _callee$(_context2) { | ||
while (1) { | ||
switch (_context2.prev = _context2.next) { | ||
case 0: | ||
_context2.next = 2; | ||
return regeneratorRuntime.awrap((0, _MessageProcessor.handleDidOpenOrSaveNotification)(params)); | ||
messageReader.listen(function (message) { | ||
try { | ||
if (message.id != null) { | ||
(0, _MessageProcessor.processIPCRequestMessage)(message, configDir, messageWriter); | ||
} else { | ||
(0, _MessageProcessor.processIPCNotificationMessage)(message, messageWriter); | ||
case 2: | ||
diagnostics = _context2.sent; | ||
if (diagnostics) { | ||
connection.sendNotification(_vscodeLanguageserver.PublishDiagnosticsNotification.type, diagnostics); | ||
} | ||
case 4: | ||
case 'end': | ||
return _context2.stop(); | ||
} | ||
} catch (error) { | ||
// Swallow error silently. | ||
} | ||
}); | ||
}, null, _this); | ||
}); | ||
connection.onNotification(_vscodeLanguageserver.DidSaveTextDocumentNotification.type, function _callee2(params) { | ||
var diagnostics; | ||
return regeneratorRuntime.async(function _callee2$(_context3) { | ||
while (1) { | ||
switch (_context3.prev = _context3.next) { | ||
case 0: | ||
_context3.next = 2; | ||
return regeneratorRuntime.awrap((0, _MessageProcessor.handleDidOpenOrSaveNotification)(params)); | ||
socket.listen(port); | ||
} | ||
case 2: | ||
diagnostics = _context3.sent; | ||
function connectWithNodeIPC(configDir) { | ||
// IPC protocol support | ||
// The language server protocol specifies that the client starts sending | ||
// messages when the server starts. Start listening from this point. | ||
var ipcWriter = new _vscodeJsonrpc.IPCMessageWriter(process); | ||
var ipcReader = new _vscodeJsonrpc.IPCMessageReader(process); | ||
ipcReader.listen(function (message) { | ||
try { | ||
if (message.id != null) { | ||
(0, _MessageProcessor.processIPCRequestMessage)(message, configDir, ipcWriter); | ||
} else { | ||
(0, _MessageProcessor.processIPCNotificationMessage)(message, ipcWriter); | ||
if (diagnostics) { | ||
connection.sendNotification(_vscodeLanguageserver.PublishDiagnosticsNotification.type, diagnostics); | ||
} | ||
case 4: | ||
case 'end': | ||
return _context3.stop(); | ||
} | ||
} | ||
} catch (error) { | ||
// Swallow error silently. | ||
} | ||
}, null, _this); | ||
}); | ||
} | ||
connection.onNotification(_vscodeLanguageserver.DidChangeTextDocumentNotification.type, function _callee3(params) { | ||
var diagnostics; | ||
return regeneratorRuntime.async(function _callee3$(_context4) { | ||
while (1) { | ||
switch (_context4.prev = _context4.next) { | ||
case 0: | ||
_context4.next = 2; | ||
return regeneratorRuntime.awrap((0, _MessageProcessor.handleDidChangeNotification)(params)); | ||
function connectWithStream(configDir) { | ||
// Stream (stdio) protocol support | ||
// Depending on the size of the query, incomplete query strings | ||
// may be streamed in. The below code tries to detect the end of current | ||
// batch of streamed data, splits the batch into appropriate JSON string, | ||
// and calls the function to process those messages. | ||
// This might get tricky since the query string needs to preserve the newline | ||
// characters to ensure the correct Range/Point values gets computed by the | ||
// language service interface methods. The current solution is to flow the | ||
// stream until aggregated data ends with the unescaped newline character, | ||
// pauses the stream and process the messages, and resumes back the stream | ||
// for another batch. | ||
var data = ''; | ||
process.stdin.setEncoding('utf8'); | ||
process.stdin.on('data', function (chunk) { | ||
data += chunk.toString(); | ||
case 2: | ||
diagnostics = _context4.sent; | ||
// Check if the current buffer contains newline character. | ||
var flagPosition = data.indexOf('\r\n'); | ||
if (flagPosition !== -1) { | ||
// There may be more than one message in the buffer. | ||
var messages = data.split('\r\n'); | ||
data = messages.pop().trim(); | ||
messages.forEach(function (message) { | ||
return (0, _MessageProcessor.processStreamMessage)(message, configDir); | ||
}); | ||
} | ||
if (diagnostics) { | ||
connection.sendNotification(_vscodeLanguageserver.PublishDiagnosticsNotification.type, diagnostics); | ||
} | ||
case 4: | ||
case 'end': | ||
return _context4.stop(); | ||
} | ||
} | ||
}, null, _this); | ||
}); | ||
connection.onNotification(_vscodeLanguageserver.DidCloseTextDocumentNotification.type, _MessageProcessor.handleDidCloseNotification); | ||
connection.onNotification(_vscodeLanguageserver.ExitNotification.type, function () { | ||
return process.exit(0); | ||
}); | ||
// Ignore cancel requests | ||
connection.onNotification('$/cancelRequest', function () { | ||
return {}; | ||
}); | ||
connection.onRequest(_vscodeLanguageserver.InitializeRequest.type, function (params, token) { | ||
return (0, _MessageProcessor.handleInitializeRequest)(params, token, configDir); | ||
}); | ||
connection.onRequest(_vscodeLanguageserver.CompletionRequest.type, _MessageProcessor.handleCompletionRequest); | ||
connection.onRequest(_vscodeLanguageserver.CompletionResolveRequest.type, function (item) { | ||
return item; | ||
}); | ||
connection.onRequest(_vscodeLanguageserver.DefinitionRequest.type, _MessageProcessor.handleDefinitionRequest); | ||
} |
{ | ||
"name": "graphql-language-service-server", | ||
"repository": "https://github.com/graphql/graphql-language-service", | ||
"version": "0.0.10", | ||
"version": "0.0.11", | ||
"description": "Server process backing the GraphQL Language Service", | ||
@@ -36,4 +36,5 @@ "contributors": [ | ||
"nullthrows": "^1.0.0", | ||
"vscode-jsonrpc": "^3.2.0" | ||
"vscode-jsonrpc": "^3.2.0", | ||
"vscode-languageserver": "^3.2.0" | ||
} | ||
} |
@@ -14,3 +14,3 @@ # GraphQL Language Service | ||
- Autocomplete suggestions (**spec-compliant**) | ||
- Hyperlink to fragment definitions | ||
- Hyperlink to fragment definitions (**spec-compliant**) | ||
- Outline view support for queries | ||
@@ -17,0 +17,0 @@ |
{ | ||
"graphql-language-service": { | ||
"version": "0.0.9" | ||
"version": "0.0.10" | ||
}, | ||
@@ -18,3 +18,3 @@ "graphql-language-server": { | ||
"graphql-language-service-server": { | ||
"version": "0.0.10" | ||
"version": "0.0.11" | ||
}, | ||
@@ -21,0 +21,0 @@ "graphql-language-service-types": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
300481
14
3984
+ Addedvscode-languageserver@^3.2.0
+ Addedgraphql-language-service-server@0.0.11(transitive)
+ Addedvscode-jsonrpc@3.5.0(transitive)
+ Addedvscode-languageserver@3.5.1(transitive)
+ Addedvscode-languageserver-protocol@3.5.1(transitive)
+ Addedvscode-languageserver-types@3.5.0(transitive)
+ Addedvscode-uri@1.0.8(transitive)
- Removedgraphql-language-service-server@0.0.10(transitive)