Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
BreakBeforeInheritanceComma: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Expand All @@ -62,8 +60,6 @@ IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
Expand All @@ -82,7 +78,6 @@ PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
Expand Down
23 changes: 23 additions & 0 deletions APIIntegrationTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@ class IntegrationTestSuite {
assert(res.status == 200);
}

void testSuccessfulCursorInfo() {
auto exampleDir = GetExamplesDir();
auto exampleName = exampleDir + std::string("some_swift.swift");
auto example = ReadFile(exampleName);
std::vector<std::string> flags;
flags.push_back("-sdk");
flags.push_back("/Applications/Xcode.app/Contents/Developer/Platforms/"
"MacOSX.platform/Developer/SDKs/MacOSX.sdk");
flags.push_back("-target");
flags.push_back("x86_64-apple-macosx10.12");

using namespace ssvim::ResultStatus;
auto body = MakeCompletionPostBody(19, 15, exampleName, example, flags);
auto responseValue = PostRequest(_boundPort, "/cursorinfo", body);
auto res = Get<response<string_body>>(responseValue);
assert(res.body.length() > 0);
assert(res.status == 200);
}

void testStatus() {
using namespace ssvim::ResultStatus;
auto responseValue = PostRequest(_boundPort, "/status", "");
Expand Down Expand Up @@ -207,8 +226,10 @@ int main(int, char const *[]) {
auto startCmd = std::string("`./build/http_server");
startCmd += " --port ";
startCmd += boundPort;
startCmd += " --log DEBUG";
startCmd += " >/dev/null`&";


// Startup the service
int started = system(startCmd.c_str());
assert(started == 0 && "Failed to start");
Expand All @@ -225,6 +246,8 @@ int main(int, char const *[]) {

std::cout << "testSuccessfulCompletion" << std::endl;
suite.testSuccessfulCompletion();
std::cout << "testSuccessfulCursorInfo" << std::endl;
suite.testSuccessfulCursorInfo();

// TODO:
// std::cout << "testRunningAfterGarbageJSON" << std::endl;
Expand Down
13 changes: 13 additions & 0 deletions IntegrationTestResponses/cursorinfo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
key.kind: source.lang.swift.ref.var.local,
key.name: "self",
key.usr: "s:10some_swift7MySwiftC15anotherFunctionyyF4selfL_ACvp",
key.filepath: "/Users/jerrymarino/.vim/bundle/iCompleteMe/third_party/icmd/third_party/swiftyswiftvim/Examples/some_swift.swift",
key.offset: 357,
key.length: 4,
key.typename: "MySwift",
key.annotated_decl: "<Declaration>let `self`: <Type usr=\"c:@M@some_swift@objc(cs)MySwift\">MySwift</Type></Declaration>",
key.fully_annotated_decl: "<decl.var.parameter><syntaxtype.keyword>let</syntaxtype.keyword> <decl.var.parameter.name>`self`</decl.var.parameter.name>: <decl.var.parameter.type><ref.class usr=\"c:@M@some_swift@objc(cs)MySwift\">MySwift</ref.class></decl.var.parameter.type></decl.var.parameter>",
key.typeusr: "_T010some_swift7MySwiftCD",
key.parent_loc: 357
}
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
integration-test:
./bootstrap
./build/integration_tests

# Mainly used for manually exploring sourcekit things
experiment:
./bootstrap
./build/test_driver

# Consider expressing this better.
format:
@$(shell for f in $$(ls *.{hpp,cpp}); do clang-format $$f; done)
49 changes: 49 additions & 0 deletions SemanticHTTPServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ EndpointImpl makeSlowTestEndpoint();
EndpointImpl makeStatusEndpoint();
EndpointImpl makeShutdownEndpoint();
EndpointImpl makeCompletionsEndpoint();
EndpointImpl makeCursorInfoEndpoint();
EndpointImpl makeDiagnosticsEndpoint();

response<string_body> notFoundResponse(req_type request);
Expand Down Expand Up @@ -104,6 +105,7 @@ class Session : public std::enable_shared_from_this<Session> {
insert_endpoint("/status", makeStatusEndpoint());
insert_endpoint("/shutdown", makeShutdownEndpoint());
insert_endpoint("/completions", makeCompletionsEndpoint());
insert_endpoint("/cursorinfo", makeCursorInfoEndpoint());
insert_endpoint("/diagnostics", makeDiagnosticsEndpoint());
insert_endpoint("/slow_test", makeSlowTestEndpoint());
}
Expand Down Expand Up @@ -332,6 +334,53 @@ EndpointImpl makeCompletionsEndpoint() {
});
}

EndpointImpl makeCursorInfoEndpoint() {
return EndpointImpl([&](std::shared_ptr<Session> session) {
// Parse in data
auto logger = session->logger();
auto bodyString = session->request().body;
logger << bodyString;
auto bodyJSON = readJSONPostBody(bodyString);

auto fileName = bodyJSON.get<std::string>("file_name");
auto column = bodyJSON.get<int>("column");
auto line = bodyJSON.get<int>("line");
auto contents = bodyJSON.get<std::string>("contents");
auto flags = as_vector<std::string>(bodyJSON, "flags");
logger << "file_name:" << fileName;
logger << "column:" << column;
logger << "line:" << line;
for (auto &f : flags) {
logger << "flags:" << f;
}

using namespace ssvim;
SwiftCompleter completer(session->logger().level());

auto files = std::vector<UnsavedFile>();
auto unsaved = UnsavedFile();
unsaved.contents = contents;
unsaved.fileName = fileName;
files.push_back(unsaved);

logger << "SEND_REQ";
auto candidates = completer.CursorInfoForLocationInFile(
fileName, line, column, files, flags);

logger << "GOT_RES";
session->logger().log(LogLevelExtreme, candidates);
// Build out response
response<string_body> res;
res.status = 200;
res.version = session->request().version;
res.fields.insert(HeaderKeyServer, HeaderValueServer);
res.fields.insert(HeaderKeyContentType, HeaderValueContentTypeJSON);
res.body = candidates;
prepare(res);
session->write(res);
});
}

// Make completions endpoint returns an endpoint that
// handles basic completion requests
//
Expand Down
104 changes: 97 additions & 7 deletions SwiftCompleter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,8 @@ struct CompletionContext {

std::vector<std::string> DefaultOSXArgs() {
return {
"-sdk",
"/Applications/Xcode.app/Contents/Developer/Platforms/"
"MacOSX.platform/Developer/SDKs/MacOSX.sdk",
"-sdk", "/Applications/Xcode.app/Contents/Developer/Platforms/"
"MacOSX.platform/Developer/SDKs/MacOSX.sdk",
"-target", "x86_64-apple-macosx10.12",
};
}
Expand All @@ -122,6 +121,7 @@ class SourceKitService {
int CompletionOpen(CompletionContext &ctx, char **oresponse);
int EditorOpen(CompletionContext &ctx, char **oresponse);
int EditorReplaceText(CompletionContext &ctx, char **oresponse);
int GetCursorInfo(CompletionContext &ctx, char **oresponse);
};
} // namespace ssvim

Expand Down Expand Up @@ -269,8 +269,8 @@ using namespace ssvim;
//
// This seemed necessary on Swift V2 when it was first written, but hopefully
// it can be improved.
static void GetOffset(CompletionContext &ctx, unsigned *offset,
std::string *CleanFile) {
static void GetCompletionOffset(CompletionContext &ctx, unsigned *offset,
std::string *CleanFile) {
auto line = ctx.line;
auto column = ctx.column;
auto fileName = ctx.sourceFilename;
Expand Down Expand Up @@ -319,6 +319,36 @@ static void GetOffset(CompletionContext &ctx, unsigned *offset,
}
}

// Get the offset for a given column, line
static void GetOffset(CompletionContext &ctx, unsigned *offset) {
auto line = ctx.line;
auto fileName = ctx.sourceFilename;
std::string unsavedInput;

for (auto unsavedFile : ctx.unsavedFiles) {
if (unsavedFile.fileName == fileName) {
unsavedInput = unsavedFile.contents;
break;
}
}

assert(unsavedInput.length() && "Missing unsaved file");

std::istringstream sourceFile(unsavedInput);
std::string someLine;
unsigned ct = 0;
unsigned currentLine = 0;
while (std::getline(sourceFile, someLine)) {
ct += someLine.length();
if (currentLine == line) {
*offset = ct;
return;
} else {
currentLine++;
}
}
}

SourceKitService::SourceKitService(ssvim::LogLevel logLevel)
: _logger(logLevel, "SKT") {
// Initialize SourceKitD resource
Expand Down Expand Up @@ -352,7 +382,7 @@ int SourceKitService::CompletionUpdate(CompletionContext &ctx,
sourcekitd_uid_get_from_cstr("source.request.codecomplete.update");
unsigned CodeCompletionOffset = 0;
std::string CleanFile;
GetOffset(ctx, &CodeCompletionOffset, &CleanFile);
GetCompletionOffset(ctx, &CodeCompletionOffset, &CleanFile);

bool isError = CodeCompleteRequest(
RequestCodeCompleteUpdate, ctx.sourceFilename.data(),
Expand All @@ -376,7 +406,7 @@ int SourceKitService::CompletionOpen(CompletionContext &ctx, char **oresponse) {
sourcekitd_uid_get_from_cstr("source.request.codecomplete.open");
unsigned CodeCompletionOffset = 0;
std::string CleanFile;
GetOffset(ctx, &CodeCompletionOffset, &CleanFile);
GetCompletionOffset(ctx, &CodeCompletionOffset, &CleanFile);

bool isError = CodeCompleteRequest(
RequestCodeCompleteOpen, ctx.sourceFilename.data(), CodeCompletionOffset,
Expand Down Expand Up @@ -437,6 +467,41 @@ int SourceKitService::EditorReplaceText(CompletionContext &ctx,
return isError;
}

int SourceKitService::GetCursorInfo(CompletionContext &ctx, char **oresponse) {
std::cout << "WILL_DECL_OPEN";
sourcekitd_uid_t RequestCursorInfo =
sourcekitd_uid_get_from_cstr("source.request.cursorinfo");
unsigned Offset = 0;
GetOffset(ctx, &Offset);

auto fileName = ctx.sourceFilename;
std::string unsavedInput;
for (auto unsavedFile : ctx.unsavedFiles) {
if (unsavedFile.fileName == fileName) {
unsavedInput = unsavedFile.contents;
break;
}
}

bool isError = CodeCompleteRequest(
RequestCursorInfo, ctx.sourceFilename.data(), Offset,
unsavedInput.c_str(), ctx.compilerArgs(), nullptr,
[&](sourcekitd_object_t response) -> bool {
if (sourcekitd_response_is_error(response)) {
return true;
}
*oresponse = PrintResponse(response);
_logger.log(LogLevelExtreme, *oresponse);
return false;
});

if (isError) {
_logger << "DID_DECL_OPEN_IS_ERROR";
}
std::cout << "DID_DECL_OPEN";
return isError;
}

#pragma mark - SwiftCompleter

namespace ssvim {
Expand Down Expand Up @@ -520,4 +585,29 @@ SwiftCompleter::DiagnosticsForFile(const std::string &filename,
auto semaresult = future.get();
return semaresult;
}

const std::string SwiftCompleter::CursorInfoForLocationInFile(const std::string &filename,
int line,
int column,
const std::vector<UnsavedFile> &unsavedFiles,
const std::vector<std::string> &flags) {
CompletionContext ctx;
ctx.sourceFilename = filename;
ctx.line = line;
ctx.column = column;
ctx.unsavedFiles = unsavedFiles;
ctx.flags = flags;

SourceKitService sktService(_logger.level());
char *response = NULL;
sktService.GetCursorInfo(ctx, &response);
if (response == NULL) {
// FIXME: Propagate SourceKitService Errors
static auto EmptyResponse = "{ 'key.results':[] }";
_logger << "Empty response";
return EmptyResponse;
}

return response;
}
} // namespace ssvim
5 changes: 5 additions & 0 deletions SwiftCompleter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,10 @@ class SwiftCompleter {
DiagnosticsForFile(const std::string &filename,
const std::vector<UnsavedFile> &unsavedFiles,
const std::vector<std::string> &flags);

const std::string
CursorInfoForLocationInFile(const std::string &filename, int line, int column,
const std::vector<UnsavedFile> &unsavedFiles,
const std::vector<std::string> &flags);
};
} // namespace ssvim