13
13
#include " absl/status/status.h"
14
14
#include " absl/status/statusor.h"
15
15
#include " absl/strings/str_cat.h"
16
+ #include " absl/strings/str_split.h"
16
17
#include " absl/synchronization/mutex.h"
17
18
#include " spdlog/fmt/fmt.h"
18
19
@@ -127,6 +128,32 @@ struct OwnedLocal {
127
128
}
128
129
};
129
130
131
+ class GemMetadata final {
132
+ string _name;
133
+ string _version;
134
+
135
+ GemMetadata (string name, string version) : _name(name), _version(version) {}
136
+
137
+ public:
138
+ GemMetadata &operator =(const GemMetadata &) = default ;
139
+
140
+ static GemMetadata tryParseOrDefault (string metadata) {
141
+ vector<string> v = absl::StrSplit (metadata, ' @' );
142
+ if (v.size () != 2 || v[0 ].empty () || v[1 ].empty ()) {
143
+ return GemMetadata{" TODO" , " TODO" };
144
+ }
145
+ return GemMetadata{v[0 ], v[1 ]};
146
+ }
147
+
148
+ const std::string &name () const {
149
+ return this ->_name ;
150
+ }
151
+
152
+ const std::string &version () const {
153
+ return this ->_version ;
154
+ }
155
+ };
156
+
130
157
// A wrapper type to handle both top-level symbols (like classes) as well as
131
158
// "inner symbols" like fields (@x). In a statically typed language, field
132
159
// symbols are like any other symbols, but in Ruby, they aren't declared
@@ -212,12 +239,12 @@ class NamedSymbolRef final {
212
239
}
213
240
214
241
// Returns OK if we were able to compute a symbol for the expression.
215
- absl::Status symbolForExpr (const core::GlobalState &gs, scip::Symbol &symbol) const {
242
+ absl::Status symbolForExpr (const core::GlobalState &gs, const GemMetadata &metadata, scip::Symbol &symbol) const {
216
243
// Don't set symbol.scheme and package.manager here because those are hard-coded to 'scip-ruby' and 'gem'
217
244
// anyways.
218
245
scip::Package package;
219
- package.set_name (" TODO " );
220
- package.set_version (" TODO " );
246
+ package.set_name (metadata. name () );
247
+ package.set_version (metadata. version () );
221
248
*symbol.mutable_package () = move (package);
222
249
223
250
InlinedVector<scip::Descriptor, 4 > descriptors;
@@ -319,6 +346,7 @@ core::Loc trimColonColonPrefix(const core::GlobalState &gs, core::Loc baseLoc) {
319
346
class SCIPState {
320
347
string symbolScratchBuffer;
321
348
UnorderedMap<NamedSymbolRef, string> symbolStringCache;
349
+ GemMetadata gemMetadata;
322
350
323
351
public:
324
352
UnorderedMap<core::FileRef, vector<scip::Occurrence>> occurrenceMap;
@@ -337,7 +365,7 @@ class SCIPState {
337
365
vector<scip::SymbolInformation> externalSymbols;
338
366
339
367
public:
340
- SCIPState () = default ;
368
+ SCIPState (GemMetadata metadata) : symbolScratchBuffer(), symbolStringCache(), gemMetadata(metadata) {}
341
369
~SCIPState () = default ;
342
370
SCIPState (SCIPState &&) = default ;
343
371
SCIPState &operator =(SCIPState &&other) = default ;
@@ -362,7 +390,7 @@ class SCIPState {
362
390
status = scip::utils::emitSymbolString (*symbol, this ->symbolScratchBuffer );
363
391
} else {
364
392
scip::Symbol symbol;
365
- status = symRef.symbolForExpr (gs, symbol);
393
+ status = symRef.symbolForExpr (gs, this -> gemMetadata , symbol);
366
394
if (!status.ok ()) {
367
395
return status;
368
396
}
@@ -459,7 +487,7 @@ class SCIPState {
459
487
std::optional<core::LocOffsets> loc = std::nullopt) {
460
488
// TODO:(varun) Should we cache here too to avoid emitting duplicate definitions?
461
489
scip::Symbol symbol;
462
- auto status = symRef.symbolForExpr (gs, symbol);
490
+ auto status = symRef.symbolForExpr (gs, this -> gemMetadata , symbol);
463
491
if (!status.ok ()) {
464
492
return status;
465
493
}
@@ -954,6 +982,7 @@ using LocalSymbolTable = UnorderedMap<core::LocalVariable, core::Loc>;
954
982
class SCIPSemanticExtension : public SemanticExtension {
955
983
public:
956
984
string indexFilePath;
985
+ scip_indexer::GemMetadata gemMetadata;
957
986
958
987
using SCIPState = sorbet::scip_indexer::SCIPState;
959
988
@@ -977,22 +1006,35 @@ class SCIPSemanticExtension : public SemanticExtension {
977
1006
//
978
1007
// We will move the state out later, so use a no-op deleter.
979
1008
return mutableState.states [this_thread::get_id ()] =
980
- shared_ptr<SCIPState>(new SCIPState (), [](SCIPState *) {});
1009
+ shared_ptr<SCIPState>(new SCIPState (gemMetadata ), [](SCIPState *) {});
981
1010
}
982
1011
}
983
1012
984
1013
void emitSymbol (const core::GlobalState &gs, core::FileRef file, ast::ClassDef *cd) const {
985
1014
auto classLoc = core::Loc (file, cd->name .loc ());
986
1015
}
987
1016
1017
+ bool doNothing () const {
1018
+ return this ->indexFilePath .empty ();
1019
+ }
1020
+
988
1021
void run (core::MutableContext &ctx, ast::ClassDef *cd) const override {
1022
+ if (this ->doNothing ()) {
1023
+ return ;
1024
+ }
989
1025
// FIXME:(varun) This is a no-op???
990
1026
emitSymbol (ctx.state , ctx.file , cd);
991
1027
};
992
1028
virtual void finishTypecheckFile (const core::GlobalState &gs, const core::FileRef &file) const override {
1029
+ if (this ->doNothing ()) {
1030
+ return ;
1031
+ }
993
1032
getSCIPState ()->saveDocument (gs, file);
994
1033
};
995
1034
virtual void finishTypecheck (const core::GlobalState &gs) const override {
1035
+ if (this ->doNothing ()) {
1036
+ return ;
1037
+ }
996
1038
scip::ToolInfo toolInfo;
997
1039
toolInfo.set_name (" scip-ruby" );
998
1040
toolInfo.set_version (sorbet_version);
@@ -1045,6 +1087,9 @@ class SCIPSemanticExtension : public SemanticExtension {
1045
1087
1046
1088
virtual void typecheck (const core::GlobalState &gs, core::FileRef file, cfg::CFG &cfg,
1047
1089
ast::MethodDef &methodDef) const override {
1090
+ if (this ->doNothing ()) {
1091
+ return ;
1092
+ }
1048
1093
auto scipState = this ->getSCIPState ();
1049
1094
if (methodDef.name != core::Names::staticInit ()) {
1050
1095
auto status = scipState->saveDefinition (gs, file, scip_indexer::NamedSymbolRef::method (methodDef.symbol ));
@@ -1067,11 +1112,12 @@ class SCIPSemanticExtension : public SemanticExtension {
1067
1112
}
1068
1113
1069
1114
virtual unique_ptr<SemanticExtension> deepCopy (const core::GlobalState &from, core::GlobalState &to) override {
1070
- return make_unique<SCIPSemanticExtension>(this ->indexFilePath );
1115
+ return make_unique<SCIPSemanticExtension>(this ->indexFilePath , this -> gemMetadata );
1071
1116
};
1072
1117
virtual void merge (const core::GlobalState &from, core::GlobalState &to, core::NameSubstitution &subst) override {};
1073
1118
1074
- SCIPSemanticExtension (string indexFilePath) : indexFilePath(indexFilePath), mutableState() {}
1119
+ SCIPSemanticExtension (string indexFilePath, scip_indexer::GemMetadata metadata)
1120
+ : indexFilePath(indexFilePath), gemMetadata(metadata), mutableState() {}
1075
1121
~SCIPSemanticExtension () {}
1076
1122
};
1077
1123
@@ -1080,15 +1126,21 @@ class SCIPSemanticExtensionProvider : public SemanticExtensionProvider {
1080
1126
void injectOptions (cxxopts::Options &optsBuilder) const override {
1081
1127
optsBuilder.add_options (" indexer" )(" index-file" , " Output SCIP index to a directory, which must already exist" ,
1082
1128
cxxopts::value<string>());
1129
+ optsBuilder.add_options (" name@version" )(
1130
+ " gem-metadata" , " Name and version pair to be used for cross-repository code navigation." ,
1131
+ cxxopts::value<string>());
1083
1132
};
1084
1133
unique_ptr<SemanticExtension> readOptions (cxxopts::ParseResult &providedOptions) const override {
1085
1134
if (providedOptions.count (" index-file" ) > 0 ) {
1086
- return make_unique<SCIPSemanticExtension>(providedOptions[" index-file" ].as <string>());
1135
+ return make_unique<SCIPSemanticExtension>(
1136
+ providedOptions[" index-file" ].as <string>(),
1137
+ scip_indexer::GemMetadata::tryParseOrDefault (
1138
+ providedOptions.count (" gem-metadata" ) > 0 ? providedOptions[" gem-metadata" ].as <string>() : " " ));
1087
1139
}
1088
1140
return this ->defaultInstance ();
1089
1141
};
1090
1142
virtual unique_ptr<SemanticExtension> defaultInstance () const override {
1091
- return make_unique<SCIPSemanticExtension>(" index.scip " );
1143
+ return make_unique<SCIPSemanticExtension>(" " , scip_indexer::GemMetadata::tryParseOrDefault ( " " ) );
1092
1144
};
1093
1145
static vector<SemanticExtensionProvider *> getProviders ();
1094
1146
virtual ~SCIPSemanticExtensionProvider () = default ;
0 commit comments