Skip to content

Commit 3fc5230

Browse files
committed
sourcekitd: define a new custom buffer for expression type response.
This custom buffer encapsulates the memory layout details of the response for the expression type request. From the client side, each expression type is represented as a tuple of {expr_offset, expr_length, printed_type}. rdar://35199889
1 parent 05d3c4b commit 3fc5230

File tree

14 files changed

+268
-28
lines changed

14 files changed

+268
-28
lines changed

lib/IDE/IDETypeChecking.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,11 +638,13 @@ class ExpressionTypeCollector: public SourceEntityWalker {
638638
{
639639
llvm::raw_svector_ostream OS(Buffer);
640640
E->getType()->getRValueType()->reconstituteSugar(true)->print(OS);
641+
// Ensure the end user can directly use the char*
642+
OS << '\0';
641643
}
642644

643645
// Add the type information to the result list.
644646
Results.push_back({Offset, Length, getTypeOffsets(Buffer.str()),
645-
static_cast<uint32_t>(Buffer.size())});
647+
static_cast<uint32_t>(Buffer.size()) - 1});
646648

647649
// Keep track of that we have a type reported for this range.
648650
AllPrintedTypes[Offset].insert(Length);
Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
1-
func foo() { return 1 }
1+
func foo() -> Int { return 1 }
2+
3+
func bar(f: Float) -> Float { return bar(f: 1) }
4+
5+
protocol P {}
6+
7+
func fooP(_ p: P) { fooP(p) }
8+
9+
class C {}
10+
11+
func ArrayC(_ a: [C]) {
12+
_ = a.count
13+
_ = a.description.count.advanced(by: 1).description
14+
}
15+
16+
struct S {
17+
let val = 4
18+
}
19+
func DictS(_ a: [Int: S]) {
20+
_ = a[2]?.val.advanced(by: 1).byteSwapped
21+
}
222

323
// RUN: %sourcekitd-test -req=collect-type %s -- %s | %FileCheck %s
4-
// CHECK: (20, 21): Int
24+
// CHECK: (183, 202): Int
25+
// CHECK: (183, 196): String
26+
// CHECK: (183, 184): [C]
27+
// CHECK: (203, 211): (Int) -> (Int) -> Int
28+
// CHECK: (211, 218): (by: Int)
29+
// CHECK: (216, 217): Int
30+
// CHECK: (257, 258): Int
31+
// CHECK: (291, 332): ()
32+
// CHECK: (291, 292): Int?
33+
// CHECK: (295, 332): Int?
34+
// CHECK: (295, 320): Int

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ struct ExpressionType {
128128
unsigned ExprOffset;
129129
unsigned ExprLength;
130130
unsigned TypeOffset;
131-
unsigned TypeLength;
132131
};
133132

134133
struct ExpressionTypesInFile {

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2057,8 +2057,7 @@ void SwiftLangSupport::collectExpressionTypes(StringRef FileName,
20572057
llvm::raw_svector_ostream OS(TypeBuffer);
20582058
ExpressionTypesInFile Result;
20592059
for (auto Item: collectExpressionType(*SF, Scratch, OS)) {
2060-
Result.Results.push_back({Item.offset, Item.length, Item.typeOffset,
2061-
Item.typeLength});
2060+
Result.Results.push_back({Item.offset, Item.length, Item.typeOffset});
20622061
}
20632062
Result.TypeBuffer = OS.str();
20642063
Receiver(Result);

tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,20 +1537,18 @@ static void printRangeInfo(sourcekitd_variant_t Info, StringRef FilenameIn,
15371537
}
15381538

15391539
static void printExpressionType(sourcekitd_variant_t Info, llvm::raw_ostream &OS) {
1540-
auto *TypeBuffer = sourcekitd_variant_dictionary_get_string(Info, KeyTypeBuffer);
1541-
sourcekitd_variant_t ExprList = sourcekitd_variant_dictionary_get_value(Info,
1542-
KeyExpressionTypeList);
1543-
unsigned Count = sourcekitd_variant_array_get_count(ExprList);
1540+
auto TypeBuffer = sourcekitd_variant_dictionary_get_value(Info, KeyExpressionTypeList);
1541+
unsigned Count = sourcekitd_variant_array_get_count(TypeBuffer);
1542+
if (!Count) {
1543+
OS << "cannot find expression types in the file\n";
1544+
return;
1545+
}
15441546
for (unsigned i = 0; i != Count; ++i) {
1545-
sourcekitd_variant_t Item = sourcekitd_variant_array_get_value(ExprList, i);
1547+
sourcekitd_variant_t Item = sourcekitd_variant_array_get_value(TypeBuffer, i);
15461548
unsigned Offset = sourcekitd_variant_dictionary_get_int64(Item, KeyExpressionOffset);
15471549
unsigned Length = sourcekitd_variant_dictionary_get_int64(Item, KeyExpressionLength);
1548-
StringRef PrintedType(TypeBuffer + sourcekitd_variant_dictionary_get_int64(Item,
1549-
KeyTypeOffset), sourcekitd_variant_dictionary_get_int64(Item, KeyTypeLength));
1550-
OS << "(" << Offset << ", " << Offset + Length << "): " << PrintedType << "\n";
1551-
}
1552-
if (!Count) {
1553-
OS << "cannot find expression types in the file\n";
1550+
OS << "(" << Offset << ", " << Offset + Length << "): " <<
1551+
sourcekitd_variant_dictionary_get_string(Item, KeyExpressionType) << "\n";
15541552
}
15551553
}
15561554

tools/SourceKit/tools/sourcekitd/include/sourcekitd/CompactArray.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class CompactArrayBuilderImpl {
2222
public:
2323
std::unique_ptr<llvm::MemoryBuffer> createBuffer() const;
2424
void appendTo(llvm::SmallVectorImpl<char> &Buf) const;
25-
25+
unsigned copyInto(char *BufPtr) const;
2626
size_t sizeInBytes() const;
2727
bool empty() const;
2828

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===--- ExpressionTypeArray.h - --------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_SOURCEKITD_EXPRESSION_TYPE_ARRAY_H
14+
#define LLVM_SOURCEKITD_EXPRESSION_TYPE_ARRAY_H
15+
16+
#include "sourcekitd/Internal.h"
17+
18+
namespace SourceKit {
19+
struct ExpressionType;
20+
}
21+
22+
namespace sourcekitd {
23+
VariantFunctions *getVariantFunctionsForExpressionTypeArray();
24+
25+
class ExpressionTypeArrayBuilder {
26+
public:
27+
ExpressionTypeArrayBuilder(llvm::StringRef PrintedType);
28+
~ExpressionTypeArrayBuilder();
29+
30+
void add(const SourceKit::ExpressionType &ExpType);
31+
std::unique_ptr<llvm::MemoryBuffer> createBuffer();
32+
static VariantFunctions Funcs;
33+
34+
private:
35+
struct Implementation;
36+
Implementation &Impl;
37+
};
38+
39+
}
40+
41+
#endif

tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ enum class CustomBufferKind {
5959
InheritedTypesArray,
6060
DocStructureElementArray,
6161
AttributesArray,
62+
ExpressionTypeArray,
6263
RawData
6364
};
6465

tools/SourceKit/tools/sourcekitd/lib/API/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(sourcekitdAPI_sources
88
Requests.cpp
99
sourcekitdAPI-Common.cpp
1010
TokenAnnotationsArray.cpp
11+
ExpressionTypeArray.cpp
1112
)
1213

1314
set(sourcekitdAPI_Darwin_sources

tools/SourceKit/tools/sourcekitd/lib/API/CompactArray.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ void CompactArrayBuilderImpl::copyInto(char *BufPtr, size_t Length) const {
9494
memcpy(BufPtr, StringBuffer.data(), StringBuffer.size());
9595
}
9696

97+
unsigned CompactArrayBuilderImpl::copyInto(char *BufPtr) const {
98+
size_t Length = sizeInBytes();
99+
copyInto(BufPtr, Length);
100+
return Length;
101+
}
102+
97103
bool CompactArrayBuilderImpl::empty() const {
98104
return EntriesBuffer.empty();
99105
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//===---------- ExpressionTypeArray.cpp -----------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "sourcekitd/ExpressionTypeArray.h"
14+
#include "sourcekitd/CompactArray.h"
15+
#include "SourceKit/Core/LLVM.h"
16+
#include "SourceKit/Core/LangSupport.h"
17+
#include "SourceKit/Support/UIdent.h"
18+
#include "DictionaryKeys.h"
19+
20+
#include "llvm/Support/MemoryBuffer.h"
21+
22+
using namespace SourceKit;
23+
using namespace sourcekitd;
24+
25+
class ExpressionTypeReader {
26+
const char *printedType;
27+
CompactArrayReader<unsigned, unsigned, unsigned> entryReader;
28+
29+
static uint64_t getHeaderValue(char *buffer, unsigned index) {
30+
uint64_t headerField;
31+
memcpy(&headerField, (uint64_t*)buffer + index, sizeof(headerField));
32+
return headerField;
33+
}
34+
35+
public:
36+
ExpressionTypeReader(char *buffer):
37+
entryReader(buffer + getHeaderValue(buffer, 0)) {
38+
// Read the printed type string buffer here.
39+
CompactArrayReader<const char*> reader(buffer + getHeaderValue(buffer, 1));
40+
reader.readEntries(0, printedType);
41+
}
42+
43+
uint64_t count() const { return entryReader.getCount(); }
44+
45+
std::pair<std::pair<unsigned, unsigned>, const char*> getExpression(uint64_t idx) {
46+
ExpressionType result;
47+
entryReader.readEntries(idx, result.ExprOffset, result.ExprLength,
48+
result.TypeOffset);
49+
return {std::make_pair(result.ExprOffset, result.ExprLength),
50+
printedType + result.TypeOffset};
51+
}
52+
53+
static bool
54+
dictionary_apply(void *buffer, size_t index,
55+
llvm::function_ref<bool(sourcekitd_uid_t,
56+
sourcekitd_variant_t)> applier) {
57+
ExpressionTypeReader reader((char*)buffer);
58+
auto result = reader.getExpression(index);
59+
#define APPLY(K, Ty, Field) \
60+
do { \
61+
sourcekitd_uid_t key = SKDUIDFromUIdent(K); \
62+
sourcekitd_variant_t var = make##Ty##Variant(Field); \
63+
if (!applier(key, var)) return false; \
64+
} while (0)
65+
APPLY(KeyExpressionOffset, Int, result.first.first);
66+
APPLY(KeyExpressionLength, Int, result.first.second);
67+
APPLY(KeyExpressionType, String, result.second);
68+
return true;
69+
}
70+
};
71+
72+
struct ExpressionTypeArrayBuilder::Implementation {
73+
StringRef printedType;
74+
SmallVector<char, 256> buffer;
75+
CompactArrayBuilder<unsigned, unsigned, unsigned> builder;
76+
CompactArrayBuilder<StringRef> strBuilder;
77+
78+
Implementation(StringRef PrintedType) { strBuilder.addEntry(PrintedType); }
79+
static sourcekitd_variant_type_t get_type(sourcekitd_variant_t var) {
80+
return SOURCEKITD_VARIANT_TYPE_ARRAY;
81+
}
82+
83+
static sourcekitd_variant_t array_get_value(sourcekitd_variant_t array,
84+
size_t index) {
85+
return {{(uintptr_t)&CompactVariantFuncs<ExpressionTypeReader>::Funcs,
86+
(uintptr_t)array.data[1], index}};
87+
}
88+
89+
// data[0] = ExpressionTypeArrayBuilder::funcs
90+
// data[1] = custum buffer
91+
static size_t array_get_count(sourcekitd_variant_t array) {
92+
ExpressionTypeReader reader((char*)array.data[1]);
93+
return reader.count();
94+
}
95+
96+
std::unique_ptr<llvm::MemoryBuffer> createBuffer() {
97+
size_t headerSize = sizeof(uint64_t) * 2;
98+
auto result = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
99+
headerSize + builder.sizeInBytes() + strBuilder.sizeInBytes());
100+
char *start = result->getBufferStart();
101+
char *headerPtr = start;
102+
char *ptr = start + headerSize;
103+
auto addBuilder = [&](CompactArrayBuilderImpl& buffer) {
104+
uint64_t offset = ptr - start;
105+
memcpy(headerPtr, &offset, sizeof(offset));
106+
headerPtr += sizeof(offset);
107+
ptr += buffer.copyInto(ptr);
108+
};
109+
110+
addBuilder(builder);
111+
addBuilder(strBuilder);
112+
assert(ptr == result->getBufferEnd());
113+
return std::move(result);
114+
}
115+
};
116+
117+
ExpressionTypeArrayBuilder::ExpressionTypeArrayBuilder(StringRef printedType)
118+
: Impl(*new Implementation(printedType)) {}
119+
120+
ExpressionTypeArrayBuilder::~ExpressionTypeArrayBuilder() {
121+
delete &Impl;
122+
}
123+
124+
void ExpressionTypeArrayBuilder::add(const ExpressionType &expType) {
125+
Impl.builder.addEntry(expType.ExprOffset, expType.ExprLength,
126+
expType.TypeOffset/*Printed type is null ended*/);
127+
}
128+
129+
std::unique_ptr<llvm::MemoryBuffer>
130+
ExpressionTypeArrayBuilder::createBuffer() {
131+
return Impl.createBuffer();
132+
}
133+
134+
VariantFunctions ExpressionTypeArrayBuilder::Funcs = {
135+
Implementation::get_type,
136+
nullptr /*AnnotArray_array_apply*/,
137+
nullptr /*AnnotArray_array_get_bool*/,
138+
Implementation::array_get_count,
139+
nullptr /*AnnotArray_array_get_int64*/,
140+
nullptr /*AnnotArray_array_get_string*/,
141+
nullptr /*AnnotArray_array_get_uid*/,
142+
Implementation::array_get_value,
143+
nullptr /*AnnotArray_bool_get_value*/,
144+
nullptr /*AnnotArray_dictionary_apply*/,
145+
nullptr /*AnnotArray_dictionary_get_bool*/,
146+
nullptr /*AnnotArray_dictionary_get_int64*/,
147+
nullptr /*AnnotArray_dictionary_get_string*/,
148+
nullptr /*AnnotArray_dictionary_get_value*/,
149+
nullptr /*AnnotArray_dictionary_get_uid*/,
150+
nullptr /*AnnotArray_string_get_length*/,
151+
nullptr /*AnnotArray_string_get_ptr*/,
152+
nullptr /*AnnotArray_int64_get_value*/,
153+
nullptr /*AnnotArray_uid_get_value*/,
154+
nullptr /*Annot_data_get_size*/,
155+
nullptr /*Annot_data_get_ptr*/,
156+
};
157+
158+
VariantFunctions *
159+
sourcekitd::getVariantFunctionsForExpressionTypeArray() {
160+
return &ExpressionTypeArrayBuilder::Funcs;
161+
}

tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "sourcekitd/DocStructureArray.h"
1616
#include "sourcekitd/DocSupportAnnotationArray.h"
1717
#include "sourcekitd/TokenAnnotationsArray.h"
18+
#include "sourcekitd/ExpressionTypeArray.h"
1819

1920
#include "SourceKit/Core/Context.h"
2021
#include "SourceKit/Core/LangSupport.h"
@@ -1742,15 +1743,12 @@ static void reportExpressionTypeInfo(const ExpressionTypesInFile &Info,
17421743
ResponseReceiver Rec) {
17431744
ResponseBuilder Builder;
17441745
auto Dict = Builder.getDictionary();
1745-
Dict.set(KeyTypeBuffer, Info.TypeBuffer);
1746-
ResponseBuilder::Array Arr = Dict.setArray(KeyExpressionTypeList);
1747-
for (auto Result: Info.Results) {
1748-
auto Elem = Arr.appendDictionary();
1749-
Elem.set(KeyExpressionOffset, Result.ExprOffset);
1750-
Elem.set(KeyExpressionLength, Result.ExprLength);
1751-
Elem.set(KeyTypeOffset, Result.TypeOffset);
1752-
Elem.set(KeyTypeLength, Result.TypeLength);
1746+
ExpressionTypeArrayBuilder ArrBuilder(Info.TypeBuffer);
1747+
for (auto &R: Info.Results) {
1748+
ArrBuilder.add(R);
17531749
}
1750+
Dict.setCustomBuffer(KeyExpressionTypeList, CustomBufferKind::ExpressionTypeArray,
1751+
ArrBuilder.createBuffer());
17541752
Rec(Builder.createResponse());
17551753
}
17561754

tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "sourcekitd/DocStructureArray.h"
1616
#include "sourcekitd/DocSupportAnnotationArray.h"
1717
#include "sourcekitd/TokenAnnotationsArray.h"
18+
#include "sourcekitd/ExpressionTypeArray.h"
1819
#include "sourcekitd/RawData.h"
1920
#include "sourcekitd/RequestResponsePrinterBase.h"
2021
#include "SourceKit/Support/UIdent.h"
@@ -621,6 +622,7 @@ static sourcekitd_variant_type_t XPCVar_get_type(sourcekitd_variant_t var) {
621622
case CustomBufferKind::InheritedTypesArray:
622623
case CustomBufferKind::DocStructureElementArray:
623624
case CustomBufferKind::AttributesArray:
625+
case CustomBufferKind::ExpressionTypeArray:
624626
return SOURCEKITD_VARIANT_TYPE_ARRAY;
625627
case CustomBufferKind::RawData:
626628
return SOURCEKITD_VARIANT_TYPE_DATA;
@@ -781,6 +783,9 @@ static sourcekitd_variant_t variantFromXPCObject(xpc_object_t obj) {
781783
case CustomBufferKind::AttributesArray:
782784
return {{ (uintptr_t)getVariantFunctionsForAttributesArray(),
783785
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
786+
case CustomBufferKind::ExpressionTypeArray:
787+
return {{ (uintptr_t)getVariantFunctionsForExpressionTypeArray(),
788+
(uintptr_t)CUSTOM_BUF_START(obj), 0 }};
784789
case sourcekitd::CustomBufferKind::RawData:
785790
return {{ (uintptr_t)getVariantFunctionsForRawData(),
786791
(uintptr_t)CUSTOM_BUF_START(obj),

0 commit comments

Comments
 (0)