From 07a380d72a13899a84cbdc35692be7a3d9246dcb Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 22 Jun 2022 19:58:34 -0700 Subject: More Language Server Improvements. (#2289) --- source/slang/slang-workspace-version.cpp | 122 ++++++++++++++----------------- 1 file changed, 55 insertions(+), 67 deletions(-) (limited to 'source/slang/slang-workspace-version.cpp') diff --git a/source/slang/slang-workspace-version.cpp b/source/slang/slang-workspace-version.cpp index 781d8a3bc..0930ca0de 100644 --- a/source/slang/slang-workspace-version.cpp +++ b/source/slang/slang-workspace-version.cpp @@ -3,6 +3,8 @@ #include "../core/slang-file-system.h" #include "../compiler-core/slang-lexer.h" #include "slang-serialize-container.h" +#include "slang-mangle.h" +#include "slang-check-impl.h" namespace Slang { @@ -30,10 +32,9 @@ DocumentVersion* Workspace::openDoc(String path, String text) { RefPtr doc = new DocumentVersion(); doc->setText(text.getUnownedSlice()); - doc->setURI(URI::fromLocalFilePath(path.getUnownedSlice())); + doc->setPath(path); openedDocuments[path] = doc; workspaceSearchPaths.Add(Path::getParentDirectory(path)); - moduleCache.invalidate(path); invalidate(); return doc.Ptr(); } @@ -51,15 +52,18 @@ void Workspace::changeDoc(const String& path, LanguageServerProtocol::Range rang auto originalText = doc->getText().getUnownedSlice(); StringBuilder newText; newText << originalText.head(startOffset) << text << originalText.tail(endOffset); - doc->setText(newText.ProduceString()); + changeDoc(doc.Ptr(), newText.ProduceString()); } - moduleCache.invalidate(path); +} + +void Workspace::changeDoc(DocumentVersion* doc, const String& newText) +{ + doc->setText(newText); invalidate(); } void Workspace::closeDoc(const String& path) { - moduleCache.invalidate(path); openedDocuments.Remove(path); invalidate(); } @@ -269,7 +273,6 @@ RefPtr Workspace::createWorkspaceVersion() slang::SessionDesc desc = {}; desc.fileSystem = this; desc.targetCount = 1; - desc.flags = slang::kSessionFlag_LanguageServer; slang::TargetDesc targetDesc = {}; targetDesc.profile = slangGlobalSession->findProfile("sm_6_6"); desc.targets = &targetDesc; @@ -308,13 +311,7 @@ RefPtr Workspace::createWorkspaceVersion() ComPtr session; slangGlobalSession->createSession(desc, session.writeRef()); version->linkage = static_cast(session.get()); - // TODO(yong): module cache does improves performance by 30%. However there are some issues - // that prevents the deserialization to resolve the imported decls from the correct module. - // This doesn't lead to crash, but may cause problems. We can enable this when the issues - // are fixed. -#if 0 - version->linkage->setModuleCache(&moduleCache); -#endif + version->linkage->contentAssistInfo.checkingMode = ContentAssistCheckingMode::General; return version; } @@ -337,7 +334,13 @@ WorkspaceVersion* Workspace::getCurrentVersion() currentVersion = createWorkspaceVersion(); return currentVersion.Ptr(); } - +WorkspaceVersion* Workspace::createVersionForCompletion() +{ + currentCompletionVersion = createWorkspaceVersion(); + currentCompletionVersion->linkage->contentAssistInfo.checkingMode = + ContentAssistCheckingMode::Completion; + return currentCompletionVersion.Ptr(); +} void* Workspace::getInterface(const Guid& uuid) { if (uuid == ISlangUnknown::getTypeGuid() || uuid == ISlangFileSystem::getTypeGuid()) @@ -416,6 +419,21 @@ static bool _isIdentifierChar(char ch) return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || ch == '_'; } +UnownedStringSlice DocumentVersion::peekIdentifier(Index& offset) +{ + Index start = offset; + Index end = offset; + while (start >= 0 && _isIdentifierChar(text[start])) + start--; + while (end < text.getLength() && _isIdentifierChar(text[end])) + end++; + offset = start + 1; + if (end > offset) + return text.getUnownedSlice().subString(start + 1, end - start - 1); + return UnownedStringSlice(""); +} + + int DocumentVersion::getTokenLength(Index line, Index col) { auto offset = getOffset(line, col); @@ -454,8 +472,19 @@ Module* WorkspaceVersion::getOrLoadModule(String path) return nullptr; ComPtr diagnosticBlob; RefPtr sourceBlob = new StringBlob((*doc)->getText()); + auto moduleName = getMangledNameFromNameString(path.getUnownedSlice()); + linkage->contentAssistInfo.primaryModuleName = linkage->getNamePool()->getName(moduleName); + linkage->contentAssistInfo.primaryModulePath = path; + // Note: + // The module at `path` may have already been loaded into the linkage previously + // due to an `import`. However that module won't get fully checked in when the checker + // is in language server mode to speed things up. + // Therefore, we always call `loadModuleFromSource` to load a fresh module instead of + // trying to reuse the existing one through `findOrImportModule`, this will result in + // redundant parsing and storage, but it saves us from the hassle of handling + // incremental/lazy checking on a previously loaded module. auto parsedModule = linkage->loadModuleFromSource( - Path::getFileNameWithoutExt(path).getBuffer(), + moduleName.getBuffer(), path.getBuffer(), sourceBlob.Ptr(), diagnosticBlob.writeRef()); @@ -474,63 +503,22 @@ Module* WorkspaceVersion::getOrLoadModule(String path) return static_cast(parsedModule); } -RefPtr SerializedModuleCache::tryLoadModule( - Linkage* linkage, String filePath) +MacroDefinitionContentAssistInfo* WorkspaceVersion::tryGetMacroDefinition(UnownedStringSlice name) { - Path::getCanonical(filePath, filePath); - if (List* rawData = serializedModules.TryGetValue(filePath)) + if (macroDefinitions.Count() == 0) { - RefPtr memStream = - new MemoryStreamBase(FileAccess::Read, rawData->getBuffer(), rawData->getCount()); - RiffContainer riffContainer; - RiffUtil::read(memStream.Ptr(), riffContainer); - SerialContainerData outData; - SerialContainerUtil::ReadOptions options; - options.linkage = linkage; - options.namePool = linkage->getNamePool(); - options.session = linkage->getSessionImpl(); - options.sharedASTBuilder = linkage->getASTBuilder()->getSharedASTBuilder(); - options.astBuilder = linkage->getASTBuilder(); - DiagnosticSink sink(linkage->getSourceManager(), Lexer::sourceLocationLexer); - options.sink = &sink; - options.sourceManager = linkage->getSourceManager(); - SLANG_RETURN_NULL_ON_FAIL(SerialContainerUtil::read(&riffContainer, options, outData)); - if (outData.modules.getCount() == 1) + // build dictionary. + for (auto& def : linkage->contentAssistInfo.preprocessorInfo.macroDefinitions) { - RefPtr module = new Module(linkage, linkage->getASTBuilder()); - auto moduleDecl = as(outData.modules[0].astRootNode); - if (moduleDecl) - { - moduleDecl->module = module.Ptr(); - module->setModuleDecl(moduleDecl); - return module; - } + macroDefinitions[def.name] = &def; } } - return nullptr; -} - -void SerializedModuleCache::storeModule( - Linkage* linkage, String filePath, RefPtr module) -{ - Path::getCanonical(filePath, filePath); - RiffContainer container; - SerialContainerUtil::WriteOptions options; - options.sourceManager = linkage->getSourceManager(); - options.compressionType = SerialCompressionType::None; - options.optionFlags = SerialOptionFlag::SourceLocation | SerialOptionFlag::ASTModule; - SerialContainerData data; - SerialContainerData::Module moduleData; - moduleData.astBuilder = linkage->getASTBuilder(); - moduleData.astRootNode = module->getModuleDecl(); - moduleData.irModule = nullptr; - data.modules.add(moduleData); - SerialContainerUtil::write(data, options, &container); - RefPtr memStream = new OwnedMemoryStream(FileAccess::Write); - RiffUtil::write(&container, memStream); - List rawData; - memStream->swapContents(rawData); - serializedModules[filePath] = _Move(rawData); + MacroDefinitionContentAssistInfo* result = nullptr; + auto namePtr = linkage->getNamePool()->tryGetName(name); + if (!namePtr) + return nullptr; + macroDefinitions.TryGetValue(namePtr, result); + return result; } } // namespace Slang -- cgit v1.2.3