From 42aff70b1c38a318c3ceab373fa59f2a709f54c3 Mon Sep 17 00:00:00 2001 From: luchuanbaker Date: Thu, 24 May 2018 12:27:51 +0800 Subject: [PATCH 1/3] Fixed messy code issues when hooking OutputDebugView API --- debugger/attach/windows/src/Shared/Utility.h | 6 +++--- .../windows/src/emmy.backend/DebugBackend.cpp | 14 +++++++++++++- .../attach/windows/src/emmy.backend/DebugBackend.h | 6 ++++++ .../windows/src/emmy.backend/DebugMessage.cpp | 1 + .../attach/windows/src/emmy.backend/DebugMessage.h | 1 + .../attach/windows/src/emmy.backend/LuaDll.cpp | 2 +- .../lua/debugger/attach/LuaAttachBridgeBase.kt | 2 +- .../lua/debugger/attach/LuaAttachMessages.kt | 4 +++- 8 files changed, 29 insertions(+), 7 deletions(-) diff --git a/debugger/attach/windows/src/Shared/Utility.h b/debugger/attach/windows/src/Shared/Utility.h index d6c07700a..94a535a4b 100644 --- a/debugger/attach/windows/src/Shared/Utility.h +++ b/debugger/attach/windows/src/Shared/Utility.h @@ -1,4 +1,4 @@ -#ifndef UTILITY_H +#ifndef UTILITY_H #define UTILITY_H #include #include @@ -16,11 +16,11 @@ struct ExeInfo */ bool GetExeInfo(LPCSTR fileName, ExeInfo&info); -// ȡǰ +// 获取当前主窗口 HWND GetCurrentWnd(); std::wstring CharToWchar(const char* c, size_t m_encode = CP_ACP); -std::string WcharToChar(const wchar_t* wp, size_t m_encode = CP_ACP); +std::string WcharToChar(const wchar_t* wp, size_t m_encode = CP_UTF8); #endif \ No newline at end of file diff --git a/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp b/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp index 70c800451..0405ed61e 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp +++ b/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp @@ -78,7 +78,7 @@ const char* MemoryReader(lua_State* L, void* data, size_t* size) BOOL inputStdin(const char* str) { - std::wstring s = CharToWchar(str); + std::wstring s = CharToWchar(str, DebugBackend::Get().GetOutputCP()); for (const wchar_t* p = s.c_str(); *p; ++p) { @@ -1232,6 +1232,11 @@ bool DebugBackend::GetIsAttached() const return WaitForSingleObject(m_detachEvent, 0) != WAIT_OBJECT_0; } +size_t DebugBackend::GetOutputCP() +{ + return m_outputCP; +} + void DebugBackend::HandleMessage(DebugMessage* message) { switch (message->getId()) @@ -1277,6 +1282,13 @@ void DebugBackend::HandleMessage(DebugMessage* message) } m_mode = Mode_Continue; m_emmyLuaFilePath = init_emmy->emmyLuaFile; + + transform(init_emmy->outputCharset.begin(), init_emmy->outputCharset.end(), init_emmy->outputCharset.begin(), toupper); + if (init_emmy->outputCharset.compare("GBK") == 0) { + m_outputCP = CP_ACP; + } else { + m_outputCP = CP_UTF8; + } m_profiler = false; DebugMessage resp(DebugMessageId::RespInitialize); m_debugPipeline->Send(&resp); diff --git a/debugger/attach/windows/src/emmy.backend/DebugBackend.h b/debugger/attach/windows/src/emmy.backend/DebugBackend.h index 7de8ff506..a8007c620 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugBackend.h +++ b/debugger/attach/windows/src/emmy.backend/DebugBackend.h @@ -266,6 +266,11 @@ class DebugBackend * if otherwise. */ bool GetIsAttached() const; + + /************************************************************************/ + /* Get the output charset in launch profile of idea */ + /************************************************************************/ + size_t GetOutputCP(); private: class Breakpoint { @@ -655,6 +660,7 @@ class DebugBackend bool m_hooked; std::string m_emmyLuaFilePath; + size_t m_outputCP; DebugPipeline* m_debugPipeline; bool m_profiler; diff --git a/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp b/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp index 020869953..97b6124f3 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp +++ b/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp @@ -29,6 +29,7 @@ void DMReqInitialize::Read(ByteInputStream* stream) stream->ReadString(emmyLuaFile); captureStd = stream->ReadBool(); captureOutputDebugString = stream->ReadBool(); + stream->ReadString(outputCharset); } DMException::DMException(): DebugMessage(DebugMessageId::Exception) diff --git a/debugger/attach/windows/src/emmy.backend/DebugMessage.h b/debugger/attach/windows/src/emmy.backend/DebugMessage.h index 0040131ec..c2fcc940d 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugMessage.h +++ b/debugger/attach/windows/src/emmy.backend/DebugMessage.h @@ -81,6 +81,7 @@ class DMReqInitialize : public DebugMessage std::string emmyLuaFile; bool captureStd; bool captureOutputDebugString; + std::string outputCharset; }; class DMException : public DebugMessage diff --git a/debugger/attach/windows/src/emmy.backend/LuaDll.cpp b/debugger/attach/windows/src/emmy.backend/LuaDll.cpp index 6a8e7c465..629332348 100644 --- a/debugger/attach/windows/src/emmy.backend/LuaDll.cpp +++ b/debugger/attach/windows/src/emmy.backend/LuaDll.cpp @@ -2024,7 +2024,7 @@ VOID WINAPI OutputDebugStringW_intercept( _In_opt_ LPCWSTR lpOutputString) { OutputDebugStringW(lpOutputString); - std::string s = WcharToChar(lpOutputString); + std::string s = WcharToChar(lpOutputString, DebugBackend::Get().GetOutputCP()); DebugBackend::Get().Message(s.c_str(), MessageType_Stdout); } diff --git a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt index 29dbcea3f..5813dc3b5 100644 --- a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt @@ -120,7 +120,7 @@ abstract class LuaAttachBridgeBase(val process: LuaAttachDebugProcessBase, val s writer = DataOutputStream(socket.getOutputStream()) ApplicationManager.getApplication().executeOnPooledThread { - send(DMReqInitialize("", emmyLua!!, captureStd, captureOutput)) + send(DMReqInitialize("", emmyLua!!, captureStd, captureOutput, process.charset)) processPack() } } catch (e: Exception) { diff --git a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt index bfdd81fcf..5add59c81 100644 --- a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt @@ -159,7 +159,8 @@ fun DataInputStream.readSize(): Long { class DMReqInitialize(private val symbolsDirectory: String, private val emmyLuaFile: String, private val captureStd: Boolean = false, - private val captureOutputDebugString: Boolean = true) + private val captureOutputDebugString: Boolean = true, + private val outputCharset: Charset = Charsets.UTF_8) : LuaAttachMessage(DebugMessageId.ReqInitialize) { override fun write(stream: DataOutputStream) { super.write(stream) @@ -167,6 +168,7 @@ class DMReqInitialize(private val symbolsDirectory: String, stream.writeString(emmyLuaFile) stream.writeBoolean(captureStd) stream.writeBoolean(captureOutputDebugString) + stream.writeString(outputCharset.name()) } } From b9c1876302364ad811a0ab8e73efd1f9b38ae70a Mon Sep 17 00:00:00 2001 From: clu Date: Tue, 8 Jan 2019 14:46:43 +0800 Subject: [PATCH 2/3] =?UTF-8?q?1=E3=80=81fix=20bug=20#209,=20#122=202?= =?UTF-8?q?=E3=80=81fix=20no=20error=20info=20in=20evaluate=20view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../codeInsight/LuaParameterInfoHandler.kt | 27 +- .../lua/debugger/attach/value/LuaXTable.kt | 42 ++- .../documentation/LuaDocumentationProvider.kt | 42 ++- .../ClassMemberCompletionProvider.kt | 69 +++++ .../intellij/lua/psi/LuaPsiResolveUtil.kt | 54 ++++ .../intellij/lua/stubs/LuaIndexExprStub.kt | 247 +++++++++++++++--- .../java/com/tang/intellij/lua/ty/TyClass.kt | 75 +++++- 7 files changed, 495 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/tang/intellij/lua/codeInsight/LuaParameterInfoHandler.kt b/src/main/java/com/tang/intellij/lua/codeInsight/LuaParameterInfoHandler.kt index 509e713e7..4c9cad942 100644 --- a/src/main/java/com/tang/intellij/lua/codeInsight/LuaParameterInfoHandler.kt +++ b/src/main/java/com/tang/intellij/lua/codeInsight/LuaParameterInfoHandler.kt @@ -20,10 +20,8 @@ import com.intellij.codeInsight.lookup.LookupElement import com.intellij.lang.parameterInfo.* import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.Processor -import com.tang.intellij.lua.psi.LuaArgs -import com.tang.intellij.lua.psi.LuaCallExpr -import com.tang.intellij.lua.psi.LuaListArgs -import com.tang.intellij.lua.psi.LuaTypes +import com.tang.intellij.lua.psi.* +import com.tang.intellij.lua.psi.impl.LuaIndexExprImpl import com.tang.intellij.lua.search.SearchContext import com.tang.intellij.lua.ty.* @@ -52,7 +50,26 @@ class LuaParameterInfoHandler : ParameterInfoHandler if (luaArgs != null) { val callExpr = luaArgs.parent as LuaCallExpr val isColonStyle = callExpr.isMethodColonCall - val type = callExpr.guessParentType(SearchContext(context.project)) + val searchContext = SearchContext(context.project) + var type = callExpr.guessParentType(searchContext) + // for chain + // add by clu on 添加对t.data.sayHello()方法的提示支持 + if (type == Ty.UNKNOWN) { + val children = luaArgs.parent.children + if (children.isNotEmpty()) { + (children[0] as? LuaIndexExpr).let { + if (it != null && it.name != null) { + val functions = resolveTypeByRoot(it, it.name!!, searchContext) + if (functions.isNotEmpty()) { + (functions[0] as? LuaIndexExpr)?.let { + type = it.guessType(searchContext) + } + } + } + } + } + } + // end val list = mutableListOf() TyUnion.each(type) { ty -> if (ty is ITyFunction) { diff --git a/src/main/java/com/tang/intellij/lua/debugger/attach/value/LuaXTable.kt b/src/main/java/com/tang/intellij/lua/debugger/attach/value/LuaXTable.kt index 5d13a31a7..3bf49302c 100644 --- a/src/main/java/com/tang/intellij/lua/debugger/attach/value/LuaXTable.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/attach/value/LuaXTable.kt @@ -90,19 +90,34 @@ open class LuaXTable(L: Long, process: LuaAttachDebugProcessBase) children.add(value) } + // fix https://github.com/EmmyLua/IntelliJ-EmmyLua/issues/122 + private fun removeNonNumberChars(str: String): String { + return str.replace("[", "").replace("]", "") + } + private fun sort() { deep = true - val sortList = mutableListOf() + val numberList = mutableListOf() + val notNumberList = mutableListOf() children.forEach { if (it is LuaXFunction) { functionList.add(it) - } else sortList.add(it) + } else { + if (removeNonNumberChars(it.name!!).toLongOrNull() == null) { + notNumberList.add(it) + } else { + numberList.add(it) + } + } } val list = XValueChildrenList() if (!functionList.isEmpty()) list.add(functionList.name, functionList) - sortList.sortBy { it.name } - sortList.forEach { list.add(it.name, it) } + numberList.sortBy { removeNonNumberChars(it.name!!).toLong() } + notNumberList.sortBy { it.name!!.toUpperCase() } + + notNumberList.forEach { list.add(it.name, it) } + numberList.forEach { list.add(it.name, it) } childrenList = list } @@ -112,14 +127,19 @@ open class LuaXTable(L: Long, process: LuaAttachDebugProcessBase) process.bridge.eval(L, evalExpr, frame.stack, 2, object : LuaAttachBridgeBase.EvalCallback { override fun onResult(result: DMRespEvaluate) { - val value = result.resultNode.value - if (value is LuaXTable) { - value.children.forEach { - add(it) + // add lua error to evaluate view + /*if (result.success && result.resultNode.success) {*/ + val value = result.resultNode.value + if (value is LuaXTable) { + value.children.forEach { + add(it) + } } - } - sort() - node.addChildren(childrenList!!, true) + sort() + node.addChildren(childrenList!!, true) + /*} else { + node.setErrorMessage(if (!result.success) "error" else result.resultNode.error) + }*/ } }) } else diff --git a/src/main/java/com/tang/intellij/lua/documentation/LuaDocumentationProvider.kt b/src/main/java/com/tang/intellij/lua/documentation/LuaDocumentationProvider.kt index fbbfc062b..5b49e35ed 100644 --- a/src/main/java/com/tang/intellij/lua/documentation/LuaDocumentationProvider.kt +++ b/src/main/java/com/tang/intellij/lua/documentation/LuaDocumentationProvider.kt @@ -22,12 +22,15 @@ import com.intellij.lang.documentation.DocumentationProvider import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.Processor import com.tang.intellij.lua.comment.psi.LuaDocTagClass import com.tang.intellij.lua.comment.psi.LuaDocTagField import com.tang.intellij.lua.editor.completion.LuaDocumentationLookupElement import com.tang.intellij.lua.psi.* import com.tang.intellij.lua.search.SearchContext +import com.tang.intellij.lua.stubs.LuaIndexExprType import com.tang.intellij.lua.stubs.index.LuaClassIndex +import com.tang.intellij.lua.stubs.index.LuaClassMemberIndex import com.tang.intellij.lua.ty.* /** @@ -100,14 +103,31 @@ class LuaDocumentationProvider : AbstractDocumentationProvider(), DocumentationP private fun renderClassMember(sb: StringBuilder, classMember: LuaClassMember) { val context = SearchContext(classMember.project) - val parentType = classMember.guessClassType(context) + var parentType = classMember.guessClassType(context) + // for chain + // add by clu on 2019-1-3 15:12:43 添加对a.b.c.d.e.f = 123中.f的parent,.e的获取支持(document中) + if (parentType == null) { + (classMember as? LuaIndexExpr)?.let { + val parentLuaIndexExpr = PsiTreeUtil.getStubChildOfType(it, LuaIndexExpr::class.java) + if (parentLuaIndexExpr != null) { + val definitions = resolveTypeByRoot(parentLuaIndexExpr, parentLuaIndexExpr.name!!, context) + if (definitions.isNotEmpty()) { + (definitions[0] as? LuaIndexExpr)?.let { + parentType = it.guessType(context) as? ITyClass + } + } + } + } + } + // end val ty = classMember.guessType(context) val tyRenderer = renderer renderDefinition(sb) { //base info if (parentType != null) { - renderTy(sb, parentType, tyRenderer) + // for chain, add: as ITyClass + renderTy(sb, parentType as ITyClass, tyRenderer) with(sb) { when (ty) { is TyFunction -> { @@ -122,9 +142,12 @@ class LuaDocumentationProvider : AbstractDocumentationProvider(), DocumentationP } } } else { + // add by clu on 2019年1月3日15:11:41 添加对a.b.c.d.e.f = 123这种格式的.f的document的支持 //NameExpr - if (classMember is LuaNameExpr) { - val nameExpr: LuaNameExpr = classMember + // for chain add: || classMember is LuaIndexExpr + if (classMember is LuaNameExpr || classMember is LuaIndexExpr) { + //val nameExpr: LuaNameExpr = classMember + val nameExpr = classMember as LuaExpr with(sb) { append(nameExpr.name) when (ty) { @@ -136,8 +159,15 @@ class LuaDocumentationProvider : AbstractDocumentationProvider(), DocumentationP } } - val stat = nameExpr.parent.parent // VAR_LIST ASSIGN_STAT - if (stat is LuaAssignStat) renderComment(sb, stat.comment, tyRenderer) + // 排除LuaIndexExpr + // for chain + if (classMember is LuaNameExpr) { + // end + val stat = nameExpr.parent.parent // VAR_LIST ASSIGN_STAT + if (stat is LuaAssignStat) renderComment(sb, stat.comment, tyRenderer) + // for chain + } + // end } } } diff --git a/src/main/java/com/tang/intellij/lua/editor/completion/ClassMemberCompletionProvider.kt b/src/main/java/com/tang/intellij/lua/editor/completion/ClassMemberCompletionProvider.kt index d0b7ce0c2..4a12625a5 100644 --- a/src/main/java/com/tang/intellij/lua/editor/completion/ClassMemberCompletionProvider.kt +++ b/src/main/java/com/tang/intellij/lua/editor/completion/ClassMemberCompletionProvider.kt @@ -16,8 +16,10 @@ package com.tang.intellij.lua.editor.completion +import com.google.common.collect.LinkedHashMultimap import com.intellij.codeInsight.completion.CompletionInitializationContext import com.intellij.codeInsight.completion.CompletionResultSet +import com.intellij.codeInsight.completion.CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED import com.intellij.codeInsight.completion.PrefixMatcher import com.intellij.codeInsight.completion.PrioritizedLookupElement import com.intellij.codeInsight.lookup.LookupElement @@ -27,6 +29,8 @@ import com.intellij.util.Processor import com.tang.intellij.lua.lang.LuaIcons import com.tang.intellij.lua.psi.* import com.tang.intellij.lua.search.SearchContext +import com.tang.intellij.lua.stubs.LuaIndexExprType +import com.tang.intellij.lua.stubs.index.LuaClassMemberIndex import com.tang.intellij.lua.ty.* enum class MemberCompletionMode { @@ -61,6 +65,71 @@ open class ClassMemberCompletionProvider : LuaCompletionProvider() { if (!Ty.isInvalid(prefixType)) { complete(isColon, project, contextTy, prefixType, completionResultSet, completionResultSet.prefixMatcher, null) } + + // for chain + // 多级t.data.name的提示 + // 查找并t.data占位类型,并扩展到结果中 + // val list = LuaIndexExprType.getAllKnownIndexLuaExprType(indexExpr, searchContext) + LuaIndexExprType.getAllKnownIndexLuaExprType(indexExpr, searchContext).forEach { + val baseType = it.key + val indexExprNames = it.value + TyUnion.each(baseType, { + if (it is ITyClass) { + // it类型是:118@F_LuaTest_src_test_t.lua + // 获取118@F_LuaTest_src_test_t.lua.__data类型 + val parentClassNameOfCurrentIndexExpr = LuaIndexExprType.getFiledNameAsClassName(it.className, indexExprNames.toTypedArray(), indexExprNames.size) + + val all = LuaClassMemberIndex.instance.get(parentClassNameOfCurrentIndexExpr.hashCode(), searchContext.project, searchContext.getScope()) + val suggestDotCountMap = LinkedHashMultimap.create() + val inputText = indexExpr.text.replace(".$DUMMY_IDENTIFIER_TRIMMED", "") // t.data. + all.forEach { + val completeText = it.text // t.data.name.a.b + if (it is LuaIndexExpr) { + suggestDotCountMap.put(completeText.replace(inputText, "").count { it == '.' }, it) + } + } + + suggestDotCountMap.keys().sorted().forEach { + suggestDotCountMap.get(it).forEach { + var suggestText = it.text.replaceFirst(inputText, "") + if (suggestText[0] == '.') { + suggestText = suggestText.substring(1) + } + + val funType = it.guessType(searchContext) + if (funType is ITyFunction) { + val luaIndexExpr = it as LuaIndexExpr + val funName = it.name!! + resolveTypeByRoot(it, it.name!!, searchContext).forEach { + // 遍历所有方法 + funType.process(Processor { + val element = TyFunctionLookupElement(funName, + luaIndexExpr, + it, + true, + isColon, + funType, + LuaIcons.CLASS_METHOD) + + element.handler = SignatureInsertHandler(it, isColon) + element.setTailText(" [${funName}]") + completionResultSet.addElement(element) + true + }) + } + } else { + if (!isColon) { + val element = LookupElementFactory.createGuessableLookupElement(suggestText, it, funType, LuaIcons.CLASS_FIELD) as LuaTypeGuessableLookupElement + completionResultSet.addElement(element) + } + } + } + } + } + }) + } + // end + //smart val nameExpr = indexExpr.prefixExpr if (nameExpr is LuaNameExpr) { diff --git a/src/main/java/com/tang/intellij/lua/psi/LuaPsiResolveUtil.kt b/src/main/java/com/tang/intellij/lua/psi/LuaPsiResolveUtil.kt index dcfddc8f5..92df5ec0e 100644 --- a/src/main/java/com/tang/intellij/lua/psi/LuaPsiResolveUtil.kt +++ b/src/main/java/com/tang/intellij/lua/psi/LuaPsiResolveUtil.kt @@ -27,7 +27,11 @@ import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.Processor import com.tang.intellij.lua.Constants import com.tang.intellij.lua.search.SearchContext +import com.tang.intellij.lua.stubs.LuaIndexExprType import com.tang.intellij.lua.stubs.index.LuaClassMemberIndex +import com.tang.intellij.lua.ty.ITy +import com.tang.intellij.lua.ty.ITyClass +import com.tang.intellij.lua.ty.TyUnion fun resolveLocal(ref: LuaNameExpr, context: SearchContext? = null) = resolveLocal(ref.name, ref, context) @@ -147,9 +151,59 @@ fun resolve(indexExpr: LuaIndexExpr, idString: String, context: SearchContext): return@Processor false true }) + // for chain + // add by clu on 2018-12-29 16:25:34 添加对无上下文的元素的支持t.data.name + val typeByRoot = resolveTypeByRoot(indexExpr, idString, context) + if (typeByRoot.isNotEmpty()) { + return typeByRoot.first() + } + // end return ret } +// for chain +/** + * t.data.name,直接通过name的父类型找自己肯定找不到的,因为对t.data, name进行indexStub的时候,t.data类型还没有index, + * 因此无法找到name的父类型t.data,自然就没有存储t.data和name的关系了,因此需要通过t找到t.data,然后再找t.__data找到name即可 + * 目前本方法只返回第一个PsiElement + */ +fun resolveTypeByRoot(indexExpr: LuaIndexExpr, idString: String, context: SearchContext): Array { + val all = mutableListOf() + LuaIndexExprType.getAllKnownIndexLuaExprType(indexExpr, context).forEach { + val baseType = it.key + val indexExprNames = it.value + val matches = mutableListOf() + TyUnion.each(baseType, { + if (it is ITyClass) { + // it类型是:118@F_LuaTest_src_test_t.lua + // 获取118@F_LuaTest_src_test_t.lua.__data类型的idString属性 + val parentClassNameOfCurrentIndexExpr = LuaIndexExprType.getFiledNameAsClassName(it.className, indexExprNames.toTypedArray(), indexExprNames.size) + LuaClassMemberIndex.process(parentClassNameOfCurrentIndexExpr, idString, context, Processor { + if (it.text.endsWith("." + idString)) { + matches.add(it) + } + true + }) + + // 只要最短的 + if (matches.isNotEmpty()) { + // 只要1个 + return@each + } + } + }) + + // 只要1个 + if (matches.isNotEmpty()) { + matches.sortBy { it.text.length } + all.add(matches.first()) + return@forEach + } + } + return all.toTypedArray() +} +// end + /** * 找到 require 的文件路径 * @param pathString 参数字符串 require "aa.bb.cc" diff --git a/src/main/java/com/tang/intellij/lua/stubs/LuaIndexExprStub.kt b/src/main/java/com/tang/intellij/lua/stubs/LuaIndexExprStub.kt index f0fe9ebe2..58c3c1e71 100644 --- a/src/main/java/com/tang/intellij/lua/stubs/LuaIndexExprStub.kt +++ b/src/main/java/com/tang/intellij/lua/stubs/LuaIndexExprStub.kt @@ -20,22 +20,18 @@ import com.intellij.psi.stubs.IndexSink import com.intellij.psi.stubs.StubElement import com.intellij.psi.stubs.StubInputStream import com.intellij.psi.stubs.StubOutputStream +import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.BitUtil import com.intellij.util.io.StringRef -import com.tang.intellij.lua.psi.LuaIndexExpr -import com.tang.intellij.lua.psi.Visibility -import com.tang.intellij.lua.psi.assignStat -import com.tang.intellij.lua.psi.docTy +import com.tang.intellij.lua.psi.* import com.tang.intellij.lua.psi.impl.LuaIndexExprImpl import com.tang.intellij.lua.search.SearchContext import com.tang.intellij.lua.stubs.index.LuaClassMemberIndex import com.tang.intellij.lua.stubs.index.StubKeys -import com.tang.intellij.lua.ty.ITy -import com.tang.intellij.lua.ty.ITyClass -import com.tang.intellij.lua.ty.TyUnion +import com.tang.intellij.lua.ty.* +import java.util.* /** - * Created by TangZX on 2017/4/12. */ class LuaIndexExprType : LuaStubElementType("INDEX_EXPR") { @@ -62,10 +58,23 @@ class LuaIndexExprType : LuaStubElementType("IND val stat = indexExpr.assignStat val docTy = stat?.comment?.docTy val classNameSet = mutableSetOf() - + // for chain + val indexExprNames = mutableListOf() + // end if (stat != null) { val context = SearchContext(indexExpr.project, indexExpr.containingFile, true) - val ty = indexExpr.guessParentType(context) + var ty = indexExpr.guessParentType(context) + // for chain + if (ty == Ty.UNKNOWN) { + /** + * local t = {} + * t.data = {} 赋值时保存t的data属性 + * t.data.name = "Tom" 赋值时,由于无法获取t.data属性所以,查找最近的类型 + */ + ty = getKnownIndexLuaExprType(indexExpr, context, indexExprNames) + } + // end + TyUnion.each(ty) { if (it is ITyClass) classNameSet.add(it.className) @@ -78,18 +87,37 @@ class LuaIndexExprType : LuaStubElementType("IND flags = BitUtil.set(flags, LuaIndexExprType.FLAG_DEPRECATED, indexExpr.isDeprecated) flags = BitUtil.set(flags, LuaIndexExprType.FLAG_BRACK, indexExpr.lbrack != null) flags = BitUtil.set(flags, LuaIndexExprType.FLAG_ASSIGN, stat != null) - - return LuaIndexExprStubImpl(classNameSet.toTypedArray(), - indexExpr.name, - flags, - docTy, - stubElement, - this) + // for chain + val stub: LuaIndexExprStub + if (indexExprNames.isEmpty()) { + stub = LuaIndexExprStubImpl(classNameSet.toTypedArray(), + indexExpr.name, + flags, + docTy, + stubElement, + this) + } else { + stub = LuaIndexExprHolderImpl(classNameSet.toTypedArray(), + indexExprNames.toTypedArray(), // 保存访问到最近的有类型的父类型的路径 + indexExpr.name, + flags, + docTy, + stubElement, + this) + } + return stub + // end } override fun serialize(indexStub: LuaIndexExprStub, stubOutputStream: StubOutputStream) { stubOutputStream.writeNames(indexStub.classNames) stubOutputStream.writeName(indexStub.name) + // for chain + if (indexStub is LuaIndexExprHolderImpl) { + stubOutputStream.writeInt(FLAG_EXTRA) + stubOutputStream.writeNames(indexStub.indexExprNames) + } + // end stubOutputStream.writeInt(indexStub.flags) stubOutputStream.writeTyNullable(indexStub.docTy) } @@ -97,32 +125,170 @@ class LuaIndexExprType : LuaStubElementType("IND override fun deserialize(stubInputStream: StubInputStream, stubElement: StubElement<*>): LuaIndexExprStub { val classNames = stubInputStream.readNames() val fieldName = stubInputStream.readName() - val flags = stubInputStream.readInt() + var flags = stubInputStream.readInt() + // for chain + var indexExprNames: Array? = null + if (flags == FLAG_EXTRA) { + indexExprNames = stubInputStream.readNames() + flags = stubInputStream.readInt() + } + // end + val docTy = stubInputStream.readTyNullable() - return LuaIndexExprStubImpl(classNames, - StringRef.toString(fieldName), - flags, - docTy, - stubElement, - this) + // for chain + if (indexExprNames == null) { + return LuaIndexExprStubImpl(classNames, + StringRef.toString(fieldName), + flags, + docTy, + stubElement, + this) + } else { + return LuaIndexExprHolderImpl(classNames, + indexExprNames, + StringRef.toString(fieldName), + flags, + docTy, + stubElement, + this) + } + // end } override fun indexStub(indexStub: LuaIndexExprStub, indexSink: IndexSink) { val fieldName = indexStub.name val classNames = indexStub.classNames if (indexStub.isAssign && classNames.isNotEmpty() && fieldName != null) { - classNames.forEach { - LuaClassMemberIndex.indexStub(indexSink, it, fieldName) + // for chain + // t.data.name的时候没有获取到t.data的类型,为其创建一个占位的类型 + if (indexStub is LuaIndexExprHolderImpl && classNames.isNotEmpty()) { + val baseClassName = classNames[0] + var parentClassName: String + val indexExprNames = indexStub.indexExprNames + var i = 1 + indexExprNames.forEach { + parentClassName = getFiledNameAsClassName(baseClassName, indexExprNames, i) + var currentFieldName: String + if (i < indexExprNames.size) { + // t.data.name.text + // 索引t.__@@data、t.__data.__@@name、 + // t.__data.__name.text + // 上面两个是占位的,便于在输入t.的时候提示t.data、t.data.name(如果没有此索引,就必须在t.data.name.的时候才提示text) + // 使用__@@前缀是为了防止resolveTypeByRoot的时候resolve到,因为此处的t.data和t.data.name并不是实际声明的地方 + currentFieldName = getFieldHolderName(indexExprNames[i]) + } else { + // t.data.name.text,最后一个属性就是当前LuaIndexExprStub声明的地方,使用.text索引 + currentFieldName = fieldName + } + LuaClassMemberIndex.indexStub(indexSink, parentClassName, currentFieldName) + i++ + } + } else { + // end + // 原始逻辑 + classNames.forEach { + LuaClassMemberIndex.indexStub(indexSink, it, fieldName) + } + // for chain } + // end indexSink.occurrence(StubKeys.SHORT_NAME, fieldName) } } companion object { + // for chain + const val FLAG_EXTRA = 0x00 // 扩展标记,如果读取到此标记则表示后面可以读取扩展数据,同理如果要写扩展数据,则先要写入扩展数据 + // end const val FLAG_DEPRECATED = 0x20 const val FLAG_BRACK = 0x40 const val FLAG_ASSIGN = 0x80 + + // for chain + /** + * 获取LuaIndexExpr最近的、有类型的父Expr的类型。 + * 比如对于LuaIndexExpr:t.data.name,获取到t,因为对于如下代码: + * t.data = {} + * t.data.name = 'Tom' + * 在对t.data.name进行LuaIndexExprStub创建的时候,t.data还未进行indexStub,因此获取到的t.data的ty是TyUnknown, + * 因此再向前获取t类型,直到获取到有类型,或者全部都没有类型(放弃) + * 找到类型后,保存当前的LuaIndexExpr和该类型的关系:t {"data"}:即:当前属性是t类型的data属性的的属性, + * 因此就给t.data创建一个占位符版本的LuaIndexExprStub + */ + fun getKnownIndexLuaExprType(_indexExpr: LuaIndexExpr, context: SearchContext, indexExprNames: MutableList): ITy { + val result = getAllKnownIndexLuaExprType(_indexExpr, context, true) + if (result.isEmpty()) { + return Ty.UNKNOWN + } + val first = result.entries.first() + indexExprNames.addAll(first.value) + return first.key + } + + fun getAllKnownIndexLuaExprType(_indexExpr: LuaIndexExpr, context: SearchContext): Map> { + return getAllKnownIndexLuaExprType(_indexExpr, context, false) + } + + private fun getAllKnownIndexLuaExprType(_indexExpr: LuaIndexExpr, context: SearchContext, onlyOne: Boolean): Map> { + val result = mutableMapOf>() + var indexExpr: LuaExpr? = _indexExpr + var indexExprType: ITy? + val indexExprNames = mutableListOf() + while (indexExpr != null && indexExpr is LuaIndexExpr && indexExpr.name != null) { + indexExprType = indexExpr.guessParentType(context) + var isValid = false + TyUnion.each(indexExprType, { + if (it is ITyClass) { + isValid = true + return@each + } + }) + if (isValid) { + result.put(indexExprType, indexExprNames.reversed()) + if (onlyOne) { + return result + } + } + indexExpr = PsiTreeUtil.getStubChildOfType(indexExpr, LuaExpr::class.java) + // 必须不能为null + if (indexExpr?.name != null) { + indexExprNames.add(indexExpr.name!!) + } else { + break + } + } + if (result.isEmpty()) { + indexExprNames.clear() + } + return result + } + + /** + * 生成Type的属性当做class的className,即:a.b.c,因为没有a.b类型,因此生成占位类:a.__b + */ + fun getFiledNameAsClassName(baseClassName: String, indexExprNames: Array, depth: Int = indexExprNames.size): String { + require(depth <= indexExprNames.size) { + "depth 不能超出 indexExprNames.size" + } + var className = baseClassName + // 如果depth = 0,,则直接返回baseClassName + if (depth >= 1) { + (1..depth).forEach { + className += ".__${indexExprNames.get(it - 1)}" + } + } + return className + } + + /** + * 获取占位属性名,即:并不是真的有这个属性,是为了该属性有子属性而动态创建的 + */ + fun getFieldHolderName(fieldName: String): String { + return "__@@$fieldName" + } + // end + } } @@ -134,12 +300,13 @@ interface LuaIndexExprStub : LuaExprStub, LuaClassMemberStub, - override val name: String?, - override val flags: Int, - override val docTy: ITy?, - stubElement: StubElement<*>, - indexType: LuaIndexExprType) +// for chain: add open +open class LuaIndexExprStubImpl(override val classNames: Array, + override val name: String?, + override val flags: Int, + override val docTy: ITy?, + stubElement: StubElement<*>, + indexType: LuaIndexExprType) : LuaStubBase(stubElement, indexType), LuaIndexExprStub { override val isDeprecated: Boolean get() = BitUtil.isSet(flags, LuaIndexExprType.FLAG_DEPRECATED) @@ -152,4 +319,18 @@ class LuaIndexExprStubImpl(override val classNames: Array, override val isAssign: Boolean get() = BitUtil.isSet(flags, LuaIndexExprType.FLAG_ASSIGN) -} \ No newline at end of file +} + +// for chain +/** + * 代替默认的LuaIndexExprStubImpl,用于对没有上下文的lua提供占位符版本的parentType + */ +class LuaIndexExprHolderImpl(override val classNames: Array, // 如果indexExprNames为空集合,则存储的是field所属的类的类名,如果不为空,则存储的是根类型的类名 + val indexExprNames: Array, // 对于每个rootClassName,访问到当前表达式的路径,比如对于t.data.a.b.name就是:['data', 'a', 'b'] + override val name: String?, + override val flags: Int, + override val docTy: ITy?, + stubElement: StubElement<*>, + indexType: LuaIndexExprType) + : LuaIndexExprStubImpl(classNames, name, flags, docTy, stubElement, indexType) +// end \ No newline at end of file diff --git a/src/main/java/com/tang/intellij/lua/ty/TyClass.kt b/src/main/java/com/tang/intellij/lua/ty/TyClass.kt index f111d99d4..f9668a2f6 100644 --- a/src/main/java/com/tang/intellij/lua/ty/TyClass.kt +++ b/src/main/java/com/tang/intellij/lua/ty/TyClass.kt @@ -17,9 +17,16 @@ package com.tang.intellij.lua.ty import com.intellij.openapi.project.Project +import com.intellij.openapi.util.UserDataHolderBase +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.ProjectAndLibrariesScope +import com.intellij.testFramework.LightVirtualFileBase import com.intellij.util.Processor +import com.intellij.util.keyFMap.ArrayBackedFMap +import com.intellij.util.keyFMap.KeyFMap import com.tang.intellij.lua.Constants import com.tang.intellij.lua.comment.psi.LuaDocTableDef import com.tang.intellij.lua.comment.psi.LuaDocTagClass @@ -259,17 +266,73 @@ fun createSerializedClass(name: String, return TySerializedClass(name, varName, supper, alias, flags) } +/** + * 嘿嘿 + */ +fun getFilePath(psiFile: PsiFile): String? { + var filePath : String? = null + if (psiFile.virtualFile != null) { + filePath = psiFile.virtualFile.path + } else { + //return "${nameDef.node.startOffset}@${nameDef.containingFile.name}" + if (psiFile is UserDataHolderBase) { + val field = UserDataHolderBase::class.java.getDeclaredField("myUserMap") + field.isAccessible = true + val fMap = field.get(psiFile) as KeyFMap + if (fMap is ArrayBackedFMap) { + val valuesFields = ArrayBackedFMap::class.java.getDeclaredField("values") + valuesFields.isAccessible = true + val values = valuesFields.get(fMap) as Array<*> + values.forEach { + if (it is VirtualFile) { + filePath = it.path + return@forEach + } + } + } else if (fMap.javaClass.name == "com.intellij.util.keyFMap.PairElementsFMap") { + val virtualFile = psiFile.viewProvider.virtualFile + if (virtualFile is LightVirtualFileBase) { + filePath = virtualFile.originalFile.path + } else { + fMap.keys.forEach { + val v = fMap.get(it) + if (v is VirtualFile) { + filePath = v.path + return@forEach + } + } + } + } + + } + } + return filePath +} + +fun getFilePathAsName(psiFile: PsiFile): String { + var filePath = getFilePath(psiFile.originalFile) + if (filePath == null) { + filePath = psiFile.name + } else { + filePath = filePath.replace(":", "").replace('/', '_') + } + + return filePath +} + fun getTableTypeName(table: LuaTableExpr): String { val stub = table.stub if (stub != null) return stub.tableTypeName - val fileName = table.containingFile.name - return "$fileName@(${table.node.startOffset})table" + return "${getFilePathAsName(table.containingFile)}@(${table.node.startOffset})table" } -fun getAnonymousType(nameDef: LuaNameDef): String { - return "${nameDef.node.startOffset}@${nameDef.containingFile.name}" +//fun getAnonymousType(nameDef: LuaNameDef): String { +fun getAnonymousType(psiElement: PsiElement): String { + /*if (nameDef.containingFile.virtualFile != null) nameDef.containingFile.virtualFile.path.replace(File.separatorChar, '_') else */ + //(nameDef.containingFile as LuaPsiFile).getUserData(Key.create("Context virtual file")) + return "${psiElement.node.startOffset}@${getFilePathAsName(psiElement.containingFile)}" } fun getGlobalTypeName(text: String): String { @@ -307,7 +370,7 @@ fun getDocTableTypeName(table: LuaDocTableDef): String { if (stub != null) return stub.className - val fileName = table.containingFile.name + val fileName = getFilePathAsName(table.containingFile)//table.containingFile.name return "10|$fileName|${table.node.startOffset}" } @@ -329,4 +392,4 @@ class TySerializedDocTable(name: String) : TySerializedClass(name) { override fun recoverAlias(context: SearchContext, aliasSubstitutor: TyAliasSubstitutor): ITy { return this } -} \ No newline at end of file +} From 8e2a8eaa96417a1ee45a441fc56ba5f361242170 Mon Sep 17 00:00:00 2001 From: clu Date: Tue, 8 Jan 2019 15:49:00 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=81=A2=E5=A4=8D=E6=88=90=E4=B8=8E?= =?UTF-8?q?=E5=8E=9F=E5=A7=8B=E7=89=88=E6=9C=AC=E4=B8=80=E6=A0=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debugger/attach/windows/src/Shared/Utility.h | 6 +++--- .../windows/src/emmy.backend/DebugBackend.cpp | 14 +------------- .../attach/windows/src/emmy.backend/DebugBackend.h | 6 ------ .../windows/src/emmy.backend/DebugMessage.cpp | 1 - .../attach/windows/src/emmy.backend/DebugMessage.h | 1 - .../attach/windows/src/emmy.backend/LuaDll.cpp | 2 +- .../lua/debugger/attach/LuaAttachBridgeBase.kt | 2 +- .../lua/debugger/attach/LuaAttachMessages.kt | 4 +--- 8 files changed, 7 insertions(+), 29 deletions(-) diff --git a/debugger/attach/windows/src/Shared/Utility.h b/debugger/attach/windows/src/Shared/Utility.h index 94a535a4b..d6c07700a 100644 --- a/debugger/attach/windows/src/Shared/Utility.h +++ b/debugger/attach/windows/src/Shared/Utility.h @@ -1,4 +1,4 @@ -#ifndef UTILITY_H +#ifndef UTILITY_H #define UTILITY_H #include #include @@ -16,11 +16,11 @@ struct ExeInfo */ bool GetExeInfo(LPCSTR fileName, ExeInfo&info); -// 获取当前主窗口 +// ȡǰ HWND GetCurrentWnd(); std::wstring CharToWchar(const char* c, size_t m_encode = CP_ACP); -std::string WcharToChar(const wchar_t* wp, size_t m_encode = CP_UTF8); +std::string WcharToChar(const wchar_t* wp, size_t m_encode = CP_ACP); #endif \ No newline at end of file diff --git a/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp b/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp index 0405ed61e..70c800451 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp +++ b/debugger/attach/windows/src/emmy.backend/DebugBackend.cpp @@ -78,7 +78,7 @@ const char* MemoryReader(lua_State* L, void* data, size_t* size) BOOL inputStdin(const char* str) { - std::wstring s = CharToWchar(str, DebugBackend::Get().GetOutputCP()); + std::wstring s = CharToWchar(str); for (const wchar_t* p = s.c_str(); *p; ++p) { @@ -1232,11 +1232,6 @@ bool DebugBackend::GetIsAttached() const return WaitForSingleObject(m_detachEvent, 0) != WAIT_OBJECT_0; } -size_t DebugBackend::GetOutputCP() -{ - return m_outputCP; -} - void DebugBackend::HandleMessage(DebugMessage* message) { switch (message->getId()) @@ -1282,13 +1277,6 @@ void DebugBackend::HandleMessage(DebugMessage* message) } m_mode = Mode_Continue; m_emmyLuaFilePath = init_emmy->emmyLuaFile; - - transform(init_emmy->outputCharset.begin(), init_emmy->outputCharset.end(), init_emmy->outputCharset.begin(), toupper); - if (init_emmy->outputCharset.compare("GBK") == 0) { - m_outputCP = CP_ACP; - } else { - m_outputCP = CP_UTF8; - } m_profiler = false; DebugMessage resp(DebugMessageId::RespInitialize); m_debugPipeline->Send(&resp); diff --git a/debugger/attach/windows/src/emmy.backend/DebugBackend.h b/debugger/attach/windows/src/emmy.backend/DebugBackend.h index a8007c620..7de8ff506 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugBackend.h +++ b/debugger/attach/windows/src/emmy.backend/DebugBackend.h @@ -266,11 +266,6 @@ class DebugBackend * if otherwise. */ bool GetIsAttached() const; - - /************************************************************************/ - /* Get the output charset in launch profile of idea */ - /************************************************************************/ - size_t GetOutputCP(); private: class Breakpoint { @@ -660,7 +655,6 @@ class DebugBackend bool m_hooked; std::string m_emmyLuaFilePath; - size_t m_outputCP; DebugPipeline* m_debugPipeline; bool m_profiler; diff --git a/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp b/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp index 97b6124f3..020869953 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp +++ b/debugger/attach/windows/src/emmy.backend/DebugMessage.cpp @@ -29,7 +29,6 @@ void DMReqInitialize::Read(ByteInputStream* stream) stream->ReadString(emmyLuaFile); captureStd = stream->ReadBool(); captureOutputDebugString = stream->ReadBool(); - stream->ReadString(outputCharset); } DMException::DMException(): DebugMessage(DebugMessageId::Exception) diff --git a/debugger/attach/windows/src/emmy.backend/DebugMessage.h b/debugger/attach/windows/src/emmy.backend/DebugMessage.h index c2fcc940d..0040131ec 100644 --- a/debugger/attach/windows/src/emmy.backend/DebugMessage.h +++ b/debugger/attach/windows/src/emmy.backend/DebugMessage.h @@ -81,7 +81,6 @@ class DMReqInitialize : public DebugMessage std::string emmyLuaFile; bool captureStd; bool captureOutputDebugString; - std::string outputCharset; }; class DMException : public DebugMessage diff --git a/debugger/attach/windows/src/emmy.backend/LuaDll.cpp b/debugger/attach/windows/src/emmy.backend/LuaDll.cpp index a3714914f..aaad19707 100644 --- a/debugger/attach/windows/src/emmy.backend/LuaDll.cpp +++ b/debugger/attach/windows/src/emmy.backend/LuaDll.cpp @@ -2025,7 +2025,7 @@ VOID WINAPI OutputDebugStringW_intercept( _In_opt_ LPCWSTR lpOutputString) { OutputDebugStringW(lpOutputString); - std::string s = WcharToChar(lpOutputString, DebugBackend::Get().GetOutputCP()); + std::string s = WcharToChar(lpOutputString); DebugBackend::Get().Message(s.c_str(), MessageType_Stdout); } diff --git a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt index 5813dc3b5..29dbcea3f 100644 --- a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachBridgeBase.kt @@ -120,7 +120,7 @@ abstract class LuaAttachBridgeBase(val process: LuaAttachDebugProcessBase, val s writer = DataOutputStream(socket.getOutputStream()) ApplicationManager.getApplication().executeOnPooledThread { - send(DMReqInitialize("", emmyLua!!, captureStd, captureOutput, process.charset)) + send(DMReqInitialize("", emmyLua!!, captureStd, captureOutput)) processPack() } } catch (e: Exception) { diff --git a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt index 5add59c81..bfdd81fcf 100644 --- a/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt +++ b/src/main/java/com/tang/intellij/lua/debugger/attach/LuaAttachMessages.kt @@ -159,8 +159,7 @@ fun DataInputStream.readSize(): Long { class DMReqInitialize(private val symbolsDirectory: String, private val emmyLuaFile: String, private val captureStd: Boolean = false, - private val captureOutputDebugString: Boolean = true, - private val outputCharset: Charset = Charsets.UTF_8) + private val captureOutputDebugString: Boolean = true) : LuaAttachMessage(DebugMessageId.ReqInitialize) { override fun write(stream: DataOutputStream) { super.write(stream) @@ -168,7 +167,6 @@ class DMReqInitialize(private val symbolsDirectory: String, stream.writeString(emmyLuaFile) stream.writeBoolean(captureStd) stream.writeBoolean(captureOutputDebugString) - stream.writeString(outputCharset.name()) } }