atom-nuclide
Version:
A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.
171 lines (160 loc) • 6.24 kB
JavaScript
Object.defineProperty(exports, '__esModule', {
value: true
});
/*
* Copyright (c) 2015-present, 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.
*/
/**
* `sourcekitten complete` returns an array of these structs as JSON.
*/
exports.default = sourceKittenCompletionToAtomSuggestion;
exports.sourceKittenSourcetextToAtomSnippet = sourceKittenSourcetextToAtomSnippet;
exports.sourceKittenKindToAtomType = sourceKittenKindToAtomType;
exports.sourceKittenKindToAtomRightLabel = sourceKittenKindToAtomRightLabel;
/**
* Transforms a `sourcekitten complete` struct into a suggestion that can be
* consumed by Atom's autocomplete suggestion API.
*/
function sourceKittenCompletionToAtomSuggestion(completion) {
return {
text: completion.descriptionKey,
snippet: sourceKittenSourcetextToAtomSnippet(completion.sourcetext),
type: sourceKittenKindToAtomType(completion.kind),
leftLabel: completion.typeName,
rightLabel: sourceKittenKindToAtomRightLabel(completion.kind),
description: completion.docBrief
};
}
/**
* Transforms SourceKitten sourcetext into a snippet that Atom can consume.
* SourceKitten sourcetext looks something like this:
*
* foobar(<#T##x: Int##Int#>, y: <#T##String#>, baz: <#T##[String]#>)
*
* Here, <#T##...#> represents the snippet location to highlight when the tab
* key is pressed. I don't know why the first snippet in the above example is
* "x: Int##Int" -- it seems to me it should be simply "x: Int" -- but we must
* handle this case as well. This function transforms this into the format
* Atom expects:
*
* foobar(${1:x: Int}, y: ${2:String}, baz: ${3:[String]})
*/
function sourceKittenSourcetextToAtomSnippet(sourcetext) {
// Atom expects numbered snippet location, beginning with 1.
var index = 1;
// Match on each instance of <#T##...#>, capturing the text in between.
// We then specify replacement text via a function.
var replacedParameters = sourcetext.replace(/<#T##(.+?)#>/g, function (_, groupOne) {
// The index is incremented after each match. We split the match group
// on ##, to handle the strange case mentioned in this function's docblock.
return '${' + index++ + ':' + groupOne.split('##')[0] + '}';
});
// When overriding instance methods, SourceKitten uses the string <#code#>
// as a marker for the body of the method. Replace this with an empty Atom
// snippet location.
return replacedParameters.replace('<#code#>', '${' + index++ + '}');
}
function sourceKittenKindToAtomType(kind) {
// TODO(bgesiak): Some of the kinds don't have predefined Atom styles that
// suit them. These should use custom HTML.
switch (kind) {
case 'source.lang.swift.keyword':
return 'keyword';
case 'source.lang.swift.decl.associatedtype':
return 'type';
case 'source.lang.swift.decl.class':
return 'class';
case 'source.lang.swift.decl.enum':
return 'class';
case 'source.lang.swift.decl.enumelement':
return 'property';
case 'source.lang.swift.decl.extension.class':
return 'class';
case 'source.lang.swift.decl.function.accessor.getter':
return 'method';
case 'source.lang.swift.decl.function.accessor.setter':
return 'method';
case 'source.lang.swift.decl.function.constructor':
return 'method';
case 'source.lang.swift.decl.function.free':
return 'function';
case 'source.lang.swift.decl.function.method.class':
return 'method';
case 'source.lang.swift.decl.function.method.instance':
return 'method';
case 'source.lang.swift.decl.function.method.static':
return 'method';
case 'source.lang.swift.decl.function.operator.infix':
return 'function';
case 'source.lang.swift.decl.function.subscript':
return 'method';
case 'source.lang.swift.decl.generic_type_param':
return 'variable';
case 'source.lang.swift.decl.protocol':
return 'type';
case 'source.lang.swift.decl.struct':
return 'class';
case 'source.lang.swift.decl.typealias':
return 'type';
case 'source.lang.swift.decl.var.global':
return 'variable';
case 'source.lang.swift.decl.var.instance':
return 'variable';
case 'source.lang.swift.decl.var.local':
return 'variable';
}
return 'variable';
}
function sourceKittenKindToAtomRightLabel(kind) {
switch (kind) {
case 'source.lang.swift.keyword':
return 'Keyword';
case 'source.lang.swift.decl.associatedtype':
return 'Associated type';
case 'source.lang.swift.decl.class':
return 'Class';
case 'source.lang.swift.decl.enum':
return 'Enum';
case 'source.lang.swift.decl.enumelement':
return 'Enum element';
case 'source.lang.swift.decl.extension.class':
return 'Class extension';
case 'source.lang.swift.decl.function.accessor.getter':
return 'Getter';
case 'source.lang.swift.decl.function.accessor.setter':
return 'Setter';
case 'source.lang.swift.decl.function.constructor':
return 'Constructor';
case 'source.lang.swift.decl.function.free':
return 'Free function';
case 'source.lang.swift.decl.function.method.class':
return 'Class method';
case 'source.lang.swift.decl.function.method.instance':
return 'Instance method';
case 'source.lang.swift.decl.function.method.static':
return 'Static method';
case 'source.lang.swift.decl.function.operator.infix':
return 'Infix operator';
case 'source.lang.swift.decl.function.subscript':
return 'Subscript';
case 'source.lang.swift.decl.generic_type_param':
return 'Generic type parameter';
case 'source.lang.swift.decl.protocol':
return 'Protocol';
case 'source.lang.swift.decl.struct':
return 'Struct';
case 'source.lang.swift.decl.typealias':
return 'Typealias';
case 'source.lang.swift.decl.var.global':
return 'Global variable';
case 'source.lang.swift.decl.var.instance':
return 'Instance variable';
case 'source.lang.swift.decl.var.local':
return 'Local variable';
}
return '';
}