yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
289f3dd22
master
1#include "slang-wasm.h" 2 3#include "../core/slang-blob.h" 4#include "../core/slang-exception.h" 5#include "../slang/slang-language-server.h" 6 7#include <slang.h> 8#include <vector> 9 10using namespace slang ; 11 12namespace slang 13{ 14namespace wgsl 15{ 16 17Error g_error ; 18 19Error getLastError () 20{ 21Error currentError = g_error ; 22g_error = {}; 23return currentError ; 24} 25 26emscripten::val getCompileTargets () 27{ 28struct TargetPair 29 { 30const char * name ; 31SlangCompileTarget target ; 32 }; 33static const TargetPair targets []= { 34 {"GLSL" ,SLANG_GLSL }, 35 {"HLSL" ,SLANG_HLSL }, 36 {"WGSL" ,SLANG_WGSL }, 37 {"SPIRV" ,SLANG_SPIRV }, 38 {"METAL" ,SLANG_METAL }, 39 {"CUDA" ,SLANG_CUDA_SOURCE }, 40 }; 41 42 std::vector < emscripten::val > result ; 43for (auto target :targets ) 44 { 45auto entry = emscripten::val::object (); 46entry .set ("name" ,target .name ); 47entry .set ("value" , (int )target .target ); 48result .push_back (entry ); 49 } 50return emscripten::val::array (result ); 51} 52 53GlobalSession * createGlobalSession () 54{ 55IGlobalSession * globalSession = nullptr ; 56 { 57SlangResult result = slang::createGlobalSession (& globalSession ); 58if (result != SLANG_OK ) 59 { 60g_error .type = std::string ("USER" ); 61g_error .result = result ; 62return nullptr ; 63 } 64 } 65 66return new GlobalSession (globalSession ); 67} 68 69Session * GlobalSession ::createSession (int compileTarget ) 70{ 71Slang ::ComPtr < ISession > session ; 72 { 73SessionDesc sessionDesc = {}; 74sessionDesc .structureSize = sizeof (sessionDesc ); 75constexpr SlangInt targetCount = 1 ; 76TargetDesc target = {}; 77target .format = (SlangCompileTarget )compileTarget ; 78if (compileTarget == SLANG_HLSL ) 79 { 80target .profile = spFindProfile (m_interface ,"sm_6_6" ); 81 } 82sessionDesc .targets = & target ; 83sessionDesc .targetCount = targetCount ; 84SlangResult result = m_interface -> createSession (sessionDesc ,session .writeRef ()); 85if (result != SLANG_OK ) 86 { 87g_error .type = std::string ("USER" ); 88g_error .result = result ; 89return nullptr ; 90 } 91 } 92 93return new Session (session ); 94} 95 96Session ::~Session () 97{ 98m_componentTypes = {}; 99auto refCount = static_cast < Slang ::Linkage *> (m_interface .get ())-> debugGetReferenceCount (); 100m_interface = nullptr ; 101} 102 103emscripten::val Session ::loadModuleFromSource ( 104const std::string & slangCode , 105const std::string & name , 106const std::string & path ) 107{ 108IModule * module = nullptr ; 109 { 110Slang ::ComPtr < slang::IBlob > diagnosticsBlob ; 111Slang ::ComPtr < ISlangBlob > slangCodeBlob = 112Slang ::RawBlob ::create (slangCode .c_str (),slangCode .size ()); 113module = m_interface -> loadModuleFromSource ( 114name .c_str (), 115path .c_str (), 116slangCodeBlob , 117diagnosticsBlob .writeRef ()); 118if (!module ) 119 { 120g_error .type = std::string ("USER" ); 121g_error .message = std::string ( 122 (char * )diagnosticsBlob -> getBufferPointer (), 123 (char * )diagnosticsBlob -> getBufferPointer ()+ diagnosticsBlob -> getBufferSize ()); 124return emscripten::val::null (); 125 } 126 } 127return emscripten::val (Module (module ,this )); 128} 129 130emscripten::val Module ::findEntryPointByName (const std::string & name ) 131{ 132Slang ::ComPtr < IEntryPoint > entryPoint ; 133 { 134SlangResult result = 135moduleInterface ()-> findEntryPointByName (name .c_str (),entryPoint .writeRef ()); 136if (result != SLANG_OK ) 137 { 138g_error .type = std::string ("USER" ); 139g_error .result = result ; 140return emscripten::val::null (); 141 } 142 } 143m_session -> addComponentType (entryPoint .get ()); 144return emscripten::val (EntryPoint (entryPoint .get (),m_session )); 145} 146 147emscripten::val Module ::findAndCheckEntryPoint (const std::string & name ,int stage ) 148{ 149Slang ::ComPtr < IEntryPoint > entryPoint ; 150 { 151Slang ::ComPtr < slang::IBlob > diagnosticsBlob ; 152SlangResult result = moduleInterface ()-> findAndCheckEntryPoint ( 153name .c_str (), 154 (SlangStage )stage , 155entryPoint .writeRef (), 156diagnosticsBlob .writeRef ()); 157if (!SLANG_SUCCEEDED (result )) 158 { 159g_error .type = std::string ("USER" ); 160g_error .result = result ; 161 162if (diagnosticsBlob -> getBufferSize ()) 163 { 164char * diagnostics = (char * )diagnosticsBlob -> getBufferPointer (); 165g_error .message = std::string (diagnostics ); 166 } 167return emscripten::val::null (); 168 } 169 } 170m_session -> addComponentType (entryPoint .get ()); 171return emscripten::val (EntryPoint (entryPoint .get (),m_session )); 172} 173 174int Module ::getDefinedEntryPointCount () 175{ 176return moduleInterface ()-> getDefinedEntryPointCount (); 177} 178 179emscripten::val Module ::getDefinedEntryPoint (int index ) 180{ 181if (moduleInterface ()-> getDefinedEntryPointCount () <=index ) 182return emscripten::val::null (); 183 184Slang ::ComPtr < IEntryPoint > entryPoint ; 185 { 186Slang ::ComPtr < slang::IBlob > diagnosticsBlob ; 187SlangResult result = moduleInterface ()-> getDefinedEntryPoint (index ,entryPoint .writeRef ()); 188if (!SLANG_SUCCEEDED (result )) 189 { 190g_error .type = std::string ("USER" ); 191g_error .result = result ; 192 193if (diagnosticsBlob -> getBufferSize ()) 194 { 195char * diagnostics = (char * )diagnosticsBlob -> getBufferPointer (); 196g_error .message = std::string (diagnostics ); 197 } 198return emscripten::val::null (); 199 } 200 } 201m_session -> addComponentType (entryPoint .get ()); 202return emscripten::val (EntryPoint (entryPoint .get (),m_session )); 203} 204 205 206emscripten::val Session ::createCompositeComponentType (emscripten::val components ) 207{ 208if (!components .isArray ()) 209 { 210g_error .type = std::string ("Slang WASM Bind" ); 211g_error .message = std::string ("createCompositeComponentType: Components must be an array" ); 212return emscripten::val::null (); 213 } 214 std::vector < emscripten::val > componentsArray = 215 emscripten::vecFromJSArray < emscripten::val > (components ); 216 217Slang ::ComPtr < IComponentType > composite ; 218 { 219 std::vector < IComponentType *> nativeComponents ; 220for (size_t i = 0U ;i < componentsArray .size ();i ++ ) 221 { 222auto componentVal = componentsArray [i ]; 223if (componentVal .instanceof (emscripten::val::module_property ("ComponentType" ))) 224 { 225auto componentType = componentVal .as < ComponentType > (); 226nativeComponents .push_back (componentType .interface ()); 227 } 228 } 229SlangResult result = m_interface -> createCompositeComponentType ( 230nativeComponents .data (), 231 (SlangInt )nativeComponents .size (), 232composite .writeRef ()); 233if (result != SLANG_OK ) 234 { 235g_error .type = std::string ("USER" ); 236g_error .result = result ; 237return emscripten::val::null (); 238 } 239 } 240addComponentType (composite .get ()); 241return emscripten::val (ComponentType (composite ,this )); 242} 243 244emscripten::val ComponentType ::link () 245{ 246Slang ::ComPtr < IComponentType > linkedProgram ; 247 { 248Slang ::ComPtr < ISlangBlob > diagnosticBlob ; 249SlangResult result = interface ()-> link (linkedProgram .writeRef (),diagnosticBlob .writeRef ()); 250if (result != SLANG_OK ) 251 { 252g_error .type = std::string ("USER" ); 253g_error .result = result ; 254g_error .message = std::string ( 255 (char * )diagnosticBlob -> getBufferPointer (), 256 (char * )diagnosticBlob -> getBufferPointer ()+ diagnosticBlob -> getBufferSize ()); 257return emscripten::val::null (); 258 } 259 } 260m_session -> addComponentType (linkedProgram .get ()); 261return emscripten::val (ComponentType (linkedProgram ,m_session )); 262} 263 264std::string ComponentType ::getEntryPointCode (int entryPointIndex ,int targetIndex ) 265{ 266 { 267Slang ::ComPtr < IBlob > kernelBlob ; 268Slang ::ComPtr < ISlangBlob > diagnosticBlob ; 269SlangResult result = interface ()-> getEntryPointCode ( 270entryPointIndex , 271targetIndex , 272kernelBlob .writeRef (), 273diagnosticBlob .writeRef ()); 274if (result != SLANG_OK ) 275 { 276g_error .type = std::string ("USER" ); 277g_error .result = result ; 278g_error .message = std::string ( 279 (char * )diagnosticBlob -> getBufferPointer (), 280 (char * )diagnosticBlob -> getBufferPointer ()+ diagnosticBlob -> getBufferSize ()); 281return "" ; 282 } 283 std::string wgslCode = std::string ( 284 (char * )kernelBlob -> getBufferPointer (), 285 (char * )kernelBlob -> getBufferPointer ()+ kernelBlob -> getBufferSize ()); 286return wgslCode ; 287 } 288 289return {}; 290} 291 292// Since result code is binary, we can't return it as a string, we will need to use emscripten::val 293// to wrap it and return it to the javascript side. 294emscripten::val ComponentType ::getEntryPointCodeBlob (int entryPointIndex ,int targetIndex ) 295{ 296Slang ::ComPtr < IBlob > kernelBlob ; 297Slang ::ComPtr < ISlangBlob > diagnosticBlob ; 298SlangResult result = interface ()-> getEntryPointCode ( 299entryPointIndex , 300targetIndex , 301kernelBlob .writeRef (), 302diagnosticBlob .writeRef ()); 303if (result != SLANG_OK ) 304 { 305g_error .type = std::string ("USER" ); 306g_error .result = result ; 307g_error .message = std::string ( 308 (char * )diagnosticBlob -> getBufferPointer (), 309 (char * )diagnosticBlob -> getBufferPointer ()+ diagnosticBlob -> getBufferSize ()); 310return {}; 311 } 312 313const uint8_t * ptr = (uint8_t * )kernelBlob -> getBufferPointer (); 314return emscripten::val (emscripten::typed_memory_view (kernelBlob -> getBufferSize (),ptr )); 315} 316 317std::string ComponentType ::getTargetCode (int targetIndex ) 318{ 319 { 320Slang ::ComPtr < IBlob > kernelBlob ; 321Slang ::ComPtr < ISlangBlob > diagnosticBlob ; 322SlangResult result = interface ()-> getTargetCode ( 323targetIndex , 324kernelBlob .writeRef (), 325diagnosticBlob .writeRef ()); 326if (result != SLANG_OK ) 327 { 328g_error .type = std::string ("USER" ); 329g_error .result = result ; 330g_error .message = std::string ( 331 (char * )diagnosticBlob -> getBufferPointer (), 332 (char * )diagnosticBlob -> getBufferPointer ()+ diagnosticBlob -> getBufferSize ()); 333return "" ; 334 } 335 std::string targetCode = std::string ( 336 (char * )kernelBlob -> getBufferPointer (), 337 (char * )kernelBlob -> getBufferPointer ()+ kernelBlob -> getBufferSize ()); 338return targetCode ; 339 } 340 341return {}; 342} 343 344// Since result code is binary, we can't return it as a string, we will need to use emscripten::val 345// to wrap it and return it to the javascript side. 346emscripten::val ComponentType ::getTargetCodeBlob (int targetIndex ) 347{ 348Slang ::ComPtr < IBlob > kernelBlob ; 349Slang ::ComPtr < ISlangBlob > diagnosticBlob ; 350SlangResult result = 351interface ()-> getTargetCode (targetIndex ,kernelBlob .writeRef (),diagnosticBlob .writeRef ()); 352if (result != SLANG_OK ) 353 { 354g_error .type = std::string ("USER" ); 355g_error .result = result ; 356g_error .message = std::string ( 357 (char * )diagnosticBlob -> getBufferPointer (), 358 (char * )diagnosticBlob -> getBufferPointer ()+ diagnosticBlob -> getBufferSize ()); 359return {}; 360 } 361 362const uint8_t * ptr = (uint8_t * )kernelBlob -> getBufferPointer (); 363return emscripten::val (emscripten::typed_memory_view (kernelBlob -> getBufferSize (),ptr )); 364} 365 366emscripten::val ComponentType ::loadStrings () 367{ 368 slang::ProgramLayout * slangReflection = interface ()-> getLayout (); 369if (!slangReflection ) 370 { 371g_error .type = std::string ("USER" ); 372g_error .message = std::string ("Failed to get reflection data" ); 373return emscripten::val::null (); 374 } 375 376SlangUInt hashedStringCount = slangReflection -> getHashedStringCount (); 377if (hashedStringCount == 0 ) 378 { 379g_error .type = std::string ("USER" ); 380g_error .message = std::string ("Warn: No reflection data found" ); 381return emscripten::val::null (); 382 } 383 384size_t stringSize = 0 ; 385 std::vector < emscripten::val > result ; 386for (SlangUInt ii = 0 ;ii < hashedStringCount ;++ ii ) 387 { 388// For each string we can fetch its bytes from the Slang 389// reflection data. 390// 391size_t stringSize = 0 ; 392char const * stringData = slangReflection -> getHashedString (ii ,& stringSize ); 393 394// Then we can compute the hash code for that string using 395// another Slang API function. 396// 397// Note: the exact hashing algorithm that Slang uses for 398// string literals is not currently documented, and may 399// change in future releases of the compiler. 400// 401int hash = spComputeStringHash (stringData ,stringSize ); 402 403 emscripten::val entry = emscripten::val::object (); 404entry .set ("hash" ,hash ); 405entry .set ("string" , std::string (stringData )); 406result .push_back (entry ); 407 } 408return emscripten::val::array (result ); 409} 410 411ProgramLayout * ComponentType ::getLayout (uint32_t targetIndex ) 412{ 413return (slang::wgsl::ProgramLayout * )interface ()-> getLayout (targetIndex ); 414} 415 416uint32_t ProgramLayout ::getParameterCount () 417{ 418return interface ()-> getParameterCount (); 419} 420 421emscripten::val ProgramLayout ::toJsonObject () 422{ 423Slang ::ComPtr < ISlangBlob > blob ; 424if (SLANG_FAILED (interface ()-> toJson (blob .writeRef ()))) 425return {}; 426auto jsonString = std::string ( 427 (char * )blob -> getBufferPointer (), 428 (char * )blob -> getBufferPointer ()+ blob -> getBufferSize ()); 429 emscripten::val parsedObject = 430 emscripten::val::global ("JSON" ).call < emscripten::val > ("parse" ,jsonString ); 431return parsedObject ; 432} 433 434VariableLayoutReflection * ProgramLayout ::getParameterByIndex (uint32_t index ) 435{ 436return (slang::wgsl::VariableLayoutReflection * )(interface ()-> getParameterByIndex (index )); 437} 438 439TypeLayoutReflection * ProgramLayout ::getGlobalParamsTypeLayout () 440{ 441return (slang::wgsl::TypeLayoutReflection * )(interface ()-> getGlobalParamsTypeLayout ()); 442} 443 444FunctionReflection * ProgramLayout ::findFunctionByName (std::string name ) 445{ 446return (slang::wgsl::FunctionReflection * )(interface ()-> findFunctionByName (name .c_str ())); 447} 448 449EntryPointReflection * ProgramLayout ::findEntryPointByName (std::string name ) 450{ 451return (slang::wgsl::EntryPointReflection * )(interface ()-> findEntryPointByName (name .c_str ())); 452} 453 454EntryPointReflection ::ThreadGroupSize EntryPointReflection ::getComputeThreadGroupSize () 455{ 456SlangUInt size [3 ]; 457interface ()-> getComputeThreadGroupSize (3 ,size ); 458return {size [0 ],size [1 ],size [2 ]}; 459} 460 461BindingType TypeLayoutReflection ::getDescriptorSetDescriptorRangeType ( 462uint32_t setIndex , 463uint32_t rangeIndex ) 464{ 465return interface ()-> getDescriptorSetDescriptorRangeType (setIndex ,rangeIndex ); 466} 467 468std::string DeclReflection ::getName () 469{ 470return interface ()-> getName (); 471} 472 473 474slang::DeclReflection ::Kind DeclReflection ::getKind () 475{ 476return interface ()-> getKind (); 477} 478 479uint32_t DeclReflection ::getChildrenCount () 480{ 481return interface ()-> getChildrenCount (); 482}; 483 484slang::wgsl::DeclReflection * DeclReflection ::getChild (uint32_t index ) 485{ 486return (slang::wgsl::DeclReflection * )interface ()-> getChild (index ); 487} 488 489slang::wgsl::TypeReflection * DeclReflection ::getType () 490{ 491return (slang::wgsl::TypeReflection * )interface ()-> getType (); 492} 493slang::wgsl::VariableReflection * DeclReflection ::asVariable () 494{ 495return (slang::wgsl::VariableReflection * )interface ()-> asVariable (); 496} 497slang::wgsl::FunctionReflection * DeclReflection ::asFunction () 498{ 499return (slang::wgsl::FunctionReflection * )interface ()-> asFunction (); 500} 501slang::wgsl::GenericReflection * DeclReflection ::asGeneric () 502{ 503return (slang::wgsl::GenericReflection * )interface ()-> asGeneric (); 504} 505slang::wgsl::DeclReflection * DeclReflection ::getParent () 506{ 507return (slang::wgsl::DeclReflection * )interface ()-> getParent (); 508} 509 510 511std::string GenericReflection ::getName () 512{ 513return interface ()-> getName (); 514} 515 516slang::wgsl::DeclReflection * GenericReflection ::asDecl () 517{ 518return (slang::wgsl::DeclReflection * )interface ()-> asDecl (); 519} 520 521uint32_t GenericReflection ::getTypeParameterCount () 522{ 523return interface ()-> getTypeParameterCount (); 524} 525slang::wgsl::VariableReflection * GenericReflection ::getTypeParameter (unsigned index ) 526{ 527return (slang::wgsl::VariableReflection * )interface ()-> getTypeParameter (index ); 528} 529uint32_t GenericReflection ::getValueParameterCount () 530{ 531return interface ()-> getValueParameterCount (); 532} 533slang::wgsl::VariableReflection * GenericReflection ::getValueParameter (unsigned index ) 534{ 535return (slang::wgsl::VariableReflection * )interface ()-> getValueParameter (index ); 536} 537 538slang::wgsl::DeclReflection * GenericReflection ::getInnerDecl () 539{ 540return (slang::wgsl::DeclReflection * )interface ()-> getInnerDecl (); 541} 542 543SlangDeclKind GenericReflection ::getInnerKind () 544{ 545return interface ()-> getInnerKind (); 546} 547 548slang::wgsl::GenericReflection * GenericReflection ::getOuterGenericContainer () 549{ 550return (slang::wgsl::GenericReflection * )interface ()-> getOuterGenericContainer (); 551} 552 553std::string VariableLayoutReflection ::getName () 554{ 555return interface ()-> getName (); 556} 557 558slang::wgsl::TypeLayoutReflection * VariableLayoutReflection ::getTypeLayout () 559{ 560return (slang::wgsl::TypeLayoutReflection * )(interface ()-> getTypeLayout ()); 561} 562 563uint32_t VariableLayoutReflection ::getBindingIndex () 564{ 565return interface ()-> getBindingIndex (); 566} 567 568std::string VariableReflection ::getName () 569{ 570return interface ()-> getName (); 571} 572 573uint32_t VariableReflection ::getUserAttributeCount () 574{ 575return interface ()-> getUserAttributeCount (); 576} 577 578slang::wgsl::UserAttribute * VariableReflection ::getUserAttributeByIndex (uint32_t index ) 579{ 580return (slang::wgsl::UserAttribute * )interface ()-> getUserAttributeByIndex (index ); 581} 582 583bool VariableReflection ::hasDefaultValue () 584{ 585return interface ()-> hasDefaultValue (); 586} 587 588slang::wgsl::TypeReflection * VariableReflection ::getType () 589{ 590return (slang::wgsl::TypeReflection * )interface ()-> getType (); 591} 592 593Modifier * VariableReflection ::findModifier (Modifier ::ID id ) 594{ 595return interface ()-> findModifier (id ); 596} 597 598slang::wgsl::VariableReflection * TypeReflection ::getFieldByIndex (uint32_t index ) 599{ 600return (slang::wgsl::VariableReflection * )interface ()-> getFieldByIndex (index ); 601} 602 603slang::TypeReflection ::ScalarType TypeReflection ::getScalarType () 604{ 605return interface ()-> getScalarType (); 606} 607 608slang::TypeReflection ::Kind TypeReflection ::getKind () 609{ 610return interface ()-> getKind (); 611} 612 613 614std::string UserAttribute ::getName () 615{ 616return interface ()-> getName (); 617} 618 619float UserAttribute ::getArgumentValueFloat (uint32_t index ) 620{ 621float value ; 622interface ()-> getArgumentValueFloat (index ,& value ); 623return value ; 624} 625 626std::string UserAttribute ::getArgumentValueString (uint32_t index ) 627{ 628size_t len = 0 ; 629const char * out = interface ()-> getArgumentValueString (index ,& len ); 630return std::string (out ,len ); 631} 632 633 634slang::wgsl::TypeReflection * UserAttribute ::getArgumentType (uint32_t index ) 635{ 636return (slang::wgsl::TypeReflection * )interface ()-> getArgumentType (index ); 637} 638 639 640uint32_t UserAttribute ::getArgumentCount () 641{ 642return interface ()-> getArgumentCount (); 643} 644 645std::string FunctionReflection ::getName () 646{ 647return interface ()-> getName (); 648} 649 650uint32_t FunctionReflection ::getUserAttributeCount () 651{ 652return interface ()-> getUserAttributeCount (); 653} 654 655slang::wgsl::UserAttribute * FunctionReflection ::getUserAttributeByIndex (uint32_t index ) 656{ 657return (slang::wgsl::UserAttribute * )interface ()-> getUserAttributeByIndex (index ); 658} 659 660namespace lsp 661{ 662Position translate (Slang ::LanguageServerProtocol ::Position p ) 663{ 664Position result ; 665result .line = p .line ; 666result .character = p .character ; 667return result ; 668} 669Range translate (Slang ::LanguageServerProtocol ::Range r ) 670{ 671Range result ; 672result .start = translate (r .start ); 673result .end = translate (r .end ); 674return result ; 675} 676Location translate (Slang ::LanguageServerProtocol ::Location l ) 677{ 678Location result ; 679result .uri = l .uri .getBuffer (); 680result .range = translate (l .range ); 681return result ; 682} 683Slang ::LanguageServerProtocol ::Position translate (Position p ) 684{ 685Slang ::LanguageServerProtocol ::Position result ; 686result .line = p .line ; 687result .character = p .character ; 688return result ; 689} 690Slang ::LanguageServerProtocol ::Range translate (Range r ) 691{ 692Slang ::LanguageServerProtocol ::Range result ; 693result .start = translate (r .start ); 694result .end = translate (r .end ); 695return result ; 696} 697Slang ::LanguageServerProtocol ::Location translate (Location l ) 698{ 699Slang ::LanguageServerProtocol ::Location result ; 700result .uri = l .uri .c_str (); 701result .range = translate (l .range ); 702return result ; 703} 704 705LanguageServer ::LanguageServer () 706{ 707Slang ::LanguageServerStartupOptions options = {}; 708m_core = new Slang ::LanguageServerCore (options ); 709init (); 710} 711 712LanguageServer ::~LanguageServer () 713{ 714delete m_core ; 715} 716 717void LanguageServer ::init () 718{ 719Slang ::LanguageServerProtocol ::InitializeParams args = {}; 720Slang ::LanguageServerProtocol ::WorkspaceFolder folder = {}; 721folder .uri = "file:///" ; 722folder .name = "/" ; 723args .workspaceFolders .add (folder ); 724m_core -> init (args ); 725} 726 727void LanguageServer ::didOpenTextDocument (std::string uri , std::string text ) 728{ 729Slang ::LanguageServerProtocol ::DidOpenTextDocumentParams args = {}; 730args .textDocument .uri = uri .c_str (); 731args .textDocument .languageId = "slang" ; 732args .textDocument .text = text .c_str (); 733m_core -> didOpenTextDocument (args ); 734} 735 736void LanguageServer ::didCloseTextDocument (std::string uri ) 737{ 738Slang ::LanguageServerProtocol ::DidCloseTextDocumentParams args = {}; 739args .textDocument .uri = uri .c_str (); 740m_core -> didCloseTextDocument (args ); 741} 742 743void LanguageServer ::didChangeTextDocument ( 744 std::string uri , 745const std::vector < lsp::TextEdit >& changes ) 746{ 747Slang ::LanguageServerProtocol ::DidChangeTextDocumentParams args = {}; 748args .textDocument .uri = uri .c_str (); 749for (auto change :changes ) 750 { 751Slang ::LanguageServerProtocol ::TextDocumentContentChangeEvent lspChange ; 752lspChange .text = change .text .c_str (); 753lspChange .range = translate (change .range ); 754args .contentChanges .add (lspChange ); 755 } 756m_core -> didChangeTextDocument (args ); 757} 758 759std::optional < lsp::Hover > LanguageServer ::hover (std::string uri , lsp::Position position ) 760{ 761Slang ::LanguageServerProtocol ::HoverParams args = {}; 762args .textDocument .uri = uri .c_str (); 763args .position = translate (position ); 764auto coreResult = m_core -> hover (args ); 765if (coreResult .isNull ) 766return std::nullopt ; 767 lsp::Hover result ; 768result .contents .kind = coreResult .result .contents .kind .getBuffer (); 769result .contents .value = coreResult .result .contents .value .getBuffer (); 770result .range = translate (coreResult .result .range ); 771return result ; 772} 773 774std::optional < std::vector < lsp::Location >> LanguageServer ::gotoDefinition ( 775 std::string uri , 776 lsp::Position position ) 777{ 778Slang ::LanguageServerProtocol ::DefinitionParams args = {}; 779args .textDocument .uri = uri .c_str (); 780args .position = translate (position ); 781auto coreResult = m_core -> gotoDefinition (args ); 782if (coreResult .isNull ) 783return std::nullopt ; 784 std::vector < lsp::Location > result ; 785for (auto location :coreResult .result ) 786result .push_back (translate (location )); 787return result ; 788} 789 790std::optional < std::vector < lsp::CompletionItem >> LanguageServer ::completion ( 791 std::string uri , 792 lsp::Position position , 793CompletionContext context ) 794{ 795Slang ::LanguageServerProtocol ::CompletionParams args = {}; 796args .textDocument .uri = uri .c_str (); 797args .position = translate (position ); 798args .context .triggerKind = context .triggerKind ; 799args .context .triggerCharacter = context .triggerCharacter .c_str (); 800auto coreResult = m_core -> completion (args ); 801if (coreResult .isNull ) 802return std::nullopt ; 803 std::vector < lsp::CompletionItem > result ; 804for (auto item :coreResult .result .items ) 805 { 806 lsp::CompletionItem completionItem ; 807completionItem .label = item .label .getBuffer (); 808completionItem .kind = item .kind ; 809completionItem .detail = item .detail .getBuffer (); 810MarkupContent documentation ; 811documentation .kind = item .documentation .kind .getBuffer (); 812documentation .value = item .documentation .value .getBuffer (); 813completionItem .documentation = documentation ; 814completionItem .textEdit = std::nullopt ; 815completionItem .data = item .data .getBuffer (); 816 std::vector < std::string > commitCharacters ; 817for (auto character :item .commitCharacters ) 818commitCharacters .push_back (character .getBuffer ()); 819completionItem .commitCharacters = commitCharacters ; 820result .push_back (completionItem ); 821 } 822return result ; 823} 824 825std::optional < lsp::CompletionItem > LanguageServer ::completionResolve (lsp::CompletionItem args ) 826{ 827Slang ::LanguageServerProtocol ::CompletionItem coreArgs = {}; 828coreArgs .label = args .label .c_str (); 829coreArgs .kind = args .kind ; 830coreArgs .detail = args .detail .c_str (); 831if (args .documentation .has_value ()) 832 { 833coreArgs .documentation .kind = args .documentation .value ().kind .c_str (); 834coreArgs .documentation .value = args .documentation .value ().value .c_str (); 835 } 836coreArgs .data = args .data .c_str (); 837if (args .commitCharacters .has_value ()) 838 { 839for (auto character :args .commitCharacters .value ()) 840coreArgs .commitCharacters .add (character .c_str ()); 841 } 842Slang ::LanguageServerProtocol ::TextEditCompletionItem editItem ; 843editItem .label = coreArgs .label ; 844editItem .kind = coreArgs .kind ; 845editItem .detail = coreArgs .detail ; 846editItem .documentation .kind = coreArgs .documentation .kind ; 847editItem .documentation .value = coreArgs .documentation .value ; 848editItem .data = coreArgs .data ; 849 850for (auto character :coreArgs .commitCharacters ) 851editItem .commitCharacters .add (character ); 852 853auto coreResult = m_core -> completionResolve (coreArgs ,editItem ); 854if (coreResult .isNull ) 855return std::nullopt ; 856 lsp::CompletionItem result ; 857result .label = coreResult .result .label .getBuffer (); 858result .kind = coreResult .result .kind ; 859result .detail = coreResult .result .detail .getBuffer (); 860MarkupContent documentation ; 861documentation .kind = coreResult .result .documentation .kind .getBuffer (); 862documentation .value = coreResult .result .documentation .value .getBuffer (); 863result .documentation = documentation ; 864result .textEdit = std::nullopt ; 865result .data = coreResult .result .data .getBuffer (); 866 std::vector < std::string > commitCharacters ; 867for (auto character :coreResult .result .commitCharacters ) 868commitCharacters .push_back (character .getBuffer ()); 869result .commitCharacters = commitCharacters ; 870return result ; 871} 872 873std::optional < std::vector < uint32_t >> LanguageServer ::semanticTokens (std::string uri ) 874{ 875Slang ::LanguageServerProtocol ::SemanticTokensParams args = {}; 876args .textDocument .uri = uri .c_str (); 877auto coreResult = m_core -> semanticTokens (args ); 878if (coreResult .isNull ) 879return std::nullopt ; 880 std::vector < uint32_t > result ; 881result .reserve ((size_t )coreResult .result .data .getCount ()); 882for (auto token :coreResult .result .data ) 883result .push_back (token ); 884return result ; 885} 886 887std::optional < lsp::SignatureHelp > LanguageServer ::signatureHelp ( 888 std::string uri , 889 lsp::Position position ) 890{ 891Slang ::LanguageServerProtocol ::SignatureHelpParams args = {}; 892args .textDocument .uri = uri .c_str (); 893args .position = translate (position ); 894auto coreResult = m_core -> signatureHelp (args ); 895if (coreResult .isNull ) 896return std::nullopt ; 897 lsp::SignatureHelp result ; 898for (auto signature :coreResult .result .signatures ) 899 { 900 lsp::SignatureInformation signatureInfo ; 901signatureInfo .label = signature .label .getBuffer (); 902signatureInfo .documentation .kind = signature .documentation .kind .getBuffer (); 903signatureInfo .documentation .value = signature .documentation .value .getBuffer (); 904for (auto parameter :signature .parameters ) 905 { 906 lsp::ParameterInformation parameterInfo ; 907parameterInfo .label [0 ]= parameter .label [0 ]; 908parameterInfo .label [1 ]= parameter .label [1 ]; 909parameterInfo .documentation .kind = parameter .documentation .kind .getBuffer (); 910parameterInfo .documentation .value = parameter .documentation .value .getBuffer (); 911signatureInfo .parameters .push_back (parameterInfo ); 912 } 913result .signatures .push_back (signatureInfo ); 914 } 915result .activeSignature = coreResult .result .activeSignature ; 916result .activeParameter = coreResult .result .activeParameter ; 917return result ; 918} 919 920lsp::DocumentSymbol translate (Slang ::LanguageServerProtocol ::DocumentSymbol symbol ) 921{ 922 lsp::DocumentSymbol result ; 923result .name = symbol .name .getBuffer (); 924result .detail = symbol .detail .getBuffer (); 925result .kind = symbol .kind ; 926result .range = translate (symbol .range ); 927result .selectionRange = translate (symbol .selectionRange ); 928for (auto child :symbol .children ) 929result .children .push_back (translate (child )); 930return result ; 931} 932 933std::optional < std::vector < lsp::DocumentSymbol >> LanguageServer ::documentSymbol (std::string uri ) 934{ 935Slang ::LanguageServerProtocol ::DocumentSymbolParams args = {}; 936args .textDocument .uri = uri .c_str (); 937auto coreResult = m_core -> documentSymbol (args ); 938if (coreResult .isNull ) 939return std::nullopt ; 940 std::vector < lsp::DocumentSymbol > result ; 941for (auto symbol :coreResult .result ) 942 { 943auto documentSymbol = translate (symbol ); 944result .push_back (documentSymbol ); 945 } 946return result ; 947} 948 949std::optional < std::vector < lsp::Diagnostics >> LanguageServer ::getDiagnostics (std::string uri ) 950{ 951 std::vector < lsp::Diagnostics > result ; 952auto module = m_core -> m_workspace -> getCurrentVersion ()-> getOrLoadModule ( 953Slang ::URI ::fromString (Slang ::UnownedStringSlice (uri .c_str ())).getPath ()); 954if (!module ) 955return std::nullopt ; 956for (auto & docDiag :m_core -> m_workspace -> getCurrentVersion ()-> diagnostics ) 957 { 958for (auto & message :docDiag .second .messages ) 959 { 960 lsp::Diagnostics diag ; 961diag .code = Slang ::String (message .code ).getBuffer (); 962diag .range = translate (message .range ); 963diag .severity = (int )message .severity ; 964diag .message = message .message .getBuffer (); 965result .push_back (diag ); 966 } 967 } 968return result ; 969} 970 971 972LanguageServer * createLanguageServer () 973{ 974return new LanguageServer (); 975} 976 977}// namespace lsp 978 979}// namespace wgsl 980}// namespace slang