mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
REPL: pass all unprocessed lines to code completion
This enables us to do code completion in function bodies and resolve local variables. Swift SVN r7118
This commit is contained in:
15
test/IDE/complete_repl_in_func_1.swift
Normal file
15
test/IDE/complete_repl_in_func_1.swift
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// RUN: %swift-ide-test -repl-code-completion -source-filename %s | FileCheck %s
|
||||||
|
|
||||||
|
// Make sure we partially type check the function body even if function body is
|
||||||
|
// missing the right brace.
|
||||||
|
// Don't add any tests at the end of the file!
|
||||||
|
//
|
||||||
|
// CHECK: Begin completions
|
||||||
|
// CHECK-DAG: SwiftDecl: a()[#Void#]{{$}}
|
||||||
|
// CHECK: End completions
|
||||||
|
struct FooStruct {
|
||||||
|
func a() {}
|
||||||
|
}
|
||||||
|
func f() {
|
||||||
|
var foo = FooStruct()
|
||||||
|
foo.
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "Immediate.h"
|
#include "Immediate.h"
|
||||||
#include "Frontend.h"
|
#include "Frontend.h"
|
||||||
#include "swift/Subsystems.h"
|
#include "swift/Subsystems.h"
|
||||||
|
#include "swift/Basic/LLVM.h"
|
||||||
#include "swift/IRGen/Options.h"
|
#include "swift/IRGen/Options.h"
|
||||||
#include "swift/Parse/Lexer.h"
|
#include "swift/Parse/Lexer.h"
|
||||||
#include "swift/AST/ASTContext.h"
|
#include "swift/AST/ASTContext.h"
|
||||||
@@ -419,6 +420,9 @@ class REPLInput {
|
|||||||
|
|
||||||
llvm::SmallVector<wchar_t, 80> PromptString;
|
llvm::SmallVector<wchar_t, 80> PromptString;
|
||||||
|
|
||||||
|
/// A buffer for all lines that the user entered, but we have not parsed yet.
|
||||||
|
llvm::SmallString<128> CurrentLines;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
REPLEnvironment &Env;
|
REPLEnvironment &Env;
|
||||||
bool Autoindent;
|
bool Autoindent;
|
||||||
@@ -490,13 +494,13 @@ public:
|
|||||||
|
|
||||||
TranslationUnit *getTU();
|
TranslationUnit *getTU();
|
||||||
|
|
||||||
REPLInputKind getREPLInput(llvm::SmallVectorImpl<char> &Line) {
|
REPLInputKind getREPLInput(SmallVectorImpl<char> &Result) {
|
||||||
int BraceCount = 0;
|
int BraceCount = 0;
|
||||||
bool HadLineContinuation = false;
|
bool HadLineContinuation = false;
|
||||||
bool UnfinishedInfixExpr = false;
|
bool UnfinishedInfixExpr = false;
|
||||||
unsigned CurChunkLines = 0;
|
unsigned CurChunkLines = 0;
|
||||||
|
|
||||||
Line.clear();
|
CurrentLines.clear();
|
||||||
|
|
||||||
// Reset color before showing the prompt.
|
// Reset color before showing the prompt.
|
||||||
if (ShowColors)
|
if (ShowColors)
|
||||||
@@ -510,7 +514,7 @@ public:
|
|||||||
PromptedForLine = false;
|
PromptedForLine = false;
|
||||||
Outdented = false;
|
Outdented = false;
|
||||||
int LineCount;
|
int LineCount;
|
||||||
size_t LineStart = Line.size();
|
size_t LineStart = CurrentLines.size();
|
||||||
const wchar_t* WLine = el_wgets(e, &LineCount);
|
const wchar_t* WLine = el_wgets(e, &LineCount);
|
||||||
if (!WLine) {
|
if (!WLine) {
|
||||||
// End-of-file.
|
// End-of-file.
|
||||||
@@ -521,15 +525,17 @@ public:
|
|||||||
|
|
||||||
if (Autoindent) {
|
if (Autoindent) {
|
||||||
size_t indent = PromptContinuationLevel*2;
|
size_t indent = PromptContinuationLevel*2;
|
||||||
Line.append(indent, ' ');
|
CurrentLines.append(indent, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
convertToUTF8(llvm::makeArrayRef(WLine, WLine + wcslen(WLine)), Line);
|
convertToUTF8(llvm::makeArrayRef(WLine, WLine + wcslen(WLine)),
|
||||||
|
CurrentLines);
|
||||||
|
|
||||||
// Special-case backslash for line continuations in the REPL.
|
// Special-case backslash for line continuations in the REPL.
|
||||||
if (Line.size() > 2 && Line.end()[-1] == '\n' && Line.end()[-2] == '\\') {
|
if (CurrentLines.size() > 2 &&
|
||||||
|
CurrentLines.end()[-1] == '\n' && CurrentLines.end()[-2] == '\\') {
|
||||||
HadLineContinuation = true;
|
HadLineContinuation = true;
|
||||||
Line.erase(Line.end() - 2);
|
CurrentLines.erase(CurrentLines.end() - 2);
|
||||||
} else {
|
} else {
|
||||||
HadLineContinuation = false;
|
HadLineContinuation = false;
|
||||||
}
|
}
|
||||||
@@ -544,12 +550,12 @@ public:
|
|||||||
|
|
||||||
// If we detect a line starting with a colon, treat it as a special
|
// If we detect a line starting with a colon, treat it as a special
|
||||||
// REPL escape.
|
// REPL escape.
|
||||||
char const *s = Line.data() + LineStart;
|
char const *s = CurrentLines.data() + LineStart;
|
||||||
char const *p = s;
|
char const *p = s;
|
||||||
while (p < Line.end() && isspace(*p)) {
|
while (p < CurrentLines.end() && isspace(*p)) {
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (p == Line.end()) {
|
if (p == CurrentLines.end()) {
|
||||||
if (BraceCount != 0 || UnfinishedInfixExpr) continue;
|
if (BraceCount != 0 || UnfinishedInfixExpr) continue;
|
||||||
return REPLInputKind::Empty;
|
return REPLInputKind::Empty;
|
||||||
}
|
}
|
||||||
@@ -566,7 +572,7 @@ public:
|
|||||||
|
|
||||||
// If we detect unbalanced braces, keep reading before
|
// If we detect unbalanced braces, keep reading before
|
||||||
// we start parsing.
|
// we start parsing.
|
||||||
while (p < Line.end()) {
|
while (p < CurrentLines.end()) {
|
||||||
if (*p == '{' || *p == '(' || *p == '[')
|
if (*p == '{' || *p == '(' || *p == '[')
|
||||||
++BraceCount;
|
++BraceCount;
|
||||||
else if (*p == '}' || *p == ')' || *p == ']')
|
else if (*p == '}' || *p == ')' || *p == ']')
|
||||||
@@ -582,9 +588,12 @@ public:
|
|||||||
}
|
}
|
||||||
} while (BraceCount > 0 || HadLineContinuation || UnfinishedInfixExpr);
|
} while (BraceCount > 0 || HadLineContinuation || UnfinishedInfixExpr);
|
||||||
|
|
||||||
|
Result.clear();
|
||||||
|
Result.append(CurrentLines.begin(), CurrentLines.end());
|
||||||
|
|
||||||
// The lexer likes null-terminated data.
|
// The lexer likes null-terminated data.
|
||||||
Line.push_back('\0');
|
Result.push_back('\0');
|
||||||
Line.pop_back();
|
Result.pop_back();
|
||||||
|
|
||||||
// Colorize the response output.
|
// Colorize the response output.
|
||||||
if (ShowColors)
|
if (ShowColors)
|
||||||
@@ -838,12 +847,13 @@ private:
|
|||||||
unsigned char onComplete(int ch) {
|
unsigned char onComplete(int ch) {
|
||||||
LineInfoW const *line = el_wline(e);
|
LineInfoW const *line = el_wline(e);
|
||||||
llvm::ArrayRef<wchar_t> wprefix(line->buffer, line->cursor - line->buffer);
|
llvm::ArrayRef<wchar_t> wprefix(line->buffer, line->cursor - line->buffer);
|
||||||
llvm::SmallString<16> prefix;
|
llvm::SmallString<16> Prefix;
|
||||||
convertToUTF8(wprefix, prefix);
|
Prefix.assign(CurrentLines);
|
||||||
|
convertToUTF8(wprefix, Prefix);
|
||||||
|
|
||||||
if (!completions) {
|
if (!completions) {
|
||||||
// If we aren't currently working with a completion set, generate one.
|
// If we aren't currently working with a completion set, generate one.
|
||||||
completions.populate(getTU(), prefix);
|
completions.populate(getTU(), Prefix);
|
||||||
// Display the common root of the found completions and beep unless we
|
// Display the common root of the found completions and beep unless we
|
||||||
// found a unique one.
|
// found a unique one.
|
||||||
insertStringRef(completions.getRoot());
|
insertStringRef(completions.getRoot());
|
||||||
|
|||||||
Reference in New Issue
Block a user