Skip to content

Commit cca6fea

Browse files
authored
Merge pull request #22835 from nkcsgexi/custom-buffer
sourcekitd: define a new custom buffer for expression type response.
2 parents 9bd3935 + d006afc commit cca6fea

File tree

15 files changed

+273
-28
lines changed

15 files changed

+273
-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-InProc.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "sourcekitd/DocSupportAnnotationArray.h"
1818
#include "sourcekitd/RawData.h"
1919
#include "sourcekitd/TokenAnnotationsArray.h"
20+
#include "sourcekitd/ExpressionTypeArray.h"
2021
#include "sourcekitd/Logging.h"
2122
#include "SourceKit/Core/LLVM.h"
2223
#include "SourceKit/Support/UIdent.h"
@@ -256,6 +257,7 @@ class SKDCustomData: public SKDObject {
256257
case CustomBufferKind::InheritedTypesArray:
257258
case CustomBufferKind::DocStructureElementArray:
258259
case CustomBufferKind::AttributesArray:
260+
case CustomBufferKind::ExpressionTypeArray:
259261
return SOURCEKITD_VARIANT_TYPE_ARRAY;
260262
case CustomBufferKind::RawData:
261263
return SOURCEKITD_VARIANT_TYPE_DATA;
@@ -982,6 +984,9 @@ static sourcekitd_variant_t variantFromSKDObject(SKDObjectRef Object) {
982984
case CustomBufferKind::AttributesArray:
983985
return {{ (uintptr_t)getVariantFunctionsForAttributesArray(),
984986
(uintptr_t)DataObject->getDataPtr(), 0 }};
987+
case CustomBufferKind::ExpressionTypeArray:
988+
return {{ (uintptr_t)getVariantFunctionsForExpressionTypeArray(),
989+
(uintptr_t)DataObject->getDataPtr(), 0 }};
985990
case CustomBufferKind::RawData:
986991
return {{ (uintptr_t)getVariantFunctionsForRawData(),
987992
(uintptr_t)DataObject->getDataPtr(),

0 commit comments

Comments
 (0)