From ca9180b2b91eea8fc55a0b36f93e76639ef27b8b Mon Sep 17 00:00:00 2001 From: Grzegorz Tomasz Czarnecki Date: Mon, 27 May 2024 16:32:31 +0200 Subject: [PATCH 01/12] [RISC-V] Fix invalid operand register in the emitted addition/subtraction code (#102074) * [RISC-V] Added sext_w pseudoinstruction * [RISC-V] Inserted INS_sext_w pseudoinstruction * [RISC-V] Started implementing new overflow logic * [RISC-V] Finished preliminar implementation of bound checks * [RISC-V] Fixed invalid 32-bit instruction * [RISC-V] Fixed 32-bit addition overflow check assert * [RISC-V] More fixes in emitter * [RISC-V] Additional fixes * [RISC-V] Fixed triple same register problem in emitInsTernary addition and subtraction logic * [RISC-V] Added sext.w to disassembler * [RISC-V] Added comments * [RISC-V] Formatted code * [RISC-V] Fixed bug * [RISC-V] Fixed other bug * [RISC-V] Fixed bug causing the int32's version to never be emitted * [RISC-V] Fixed assert * [RISC-V] Improved comment * [RISC-V] Fixed comment * [RISC-V] Fixed temp reg acquiring * [RISC-V] Removed asserts * Fixed NodeInternalRegister's GetSingle method's comment * [RISC-V] Revoked more changes * [RISC-V] Revoked more changes * [RISC-V] Embedded sext_w into codegen * [RISC-V] Fixed some comments * [RISC-V] Added additional comment * [RISC-V] Improvements * [RISC-V] Added old comment --- src/coreclr/jit/codegencommon.cpp | 2 +- src/coreclr/jit/codegenriscv64.cpp | 8 +- src/coreclr/jit/emitriscv64.cpp | 134 ++++++++++++++++------------- src/coreclr/jit/instrsriscv64.h | 1 + 4 files changed, 81 insertions(+), 64 deletions(-) diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index f8963becfe419a..a2ac6832d8222a 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -110,7 +110,7 @@ regNumber NodeInternalRegisters::Extract(GenTree* tree, regMaskTP mask) } //------------------------------------------------------------------------ -// GetSingleTempReg: There is expected to be exactly one available temporary register +// GetSingle: There is expected to be exactly one available temporary register // in the given mask in the internal register set. Get that register. No future calls to get // a temporary register are expected. Removes the register from the set, but only in // DEBUG to avoid doing unnecessary work in non-DEBUG builds. diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index e4e2ede54b3768..16a4f91949c207 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -4006,7 +4006,7 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) else { imm = static_cast(imm); - emit->emitIns_R_R_I(INS_addiw, EA_8BYTE, tmpRegOp1, regOp1, 0); + emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1); } regOp1 = tmpRegOp1; break; @@ -4033,7 +4033,7 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) } else { - emit->emitIns_R_R_I(INS_addiw, EA_8BYTE, tmpRegOp1, regOp1, 0); + emit->emitIns_R_R(INS_sext_w, EA_8BYTE, tmpRegOp1, regOp1); } regOp1 = tmpRegOp1; } @@ -5672,13 +5672,13 @@ void CodeGen::genRangeCheck(GenTree* oper) if (genActualType(length) == TYP_INT) { regNumber tempReg = internalRegisters.Extract(oper); - GetEmitter()->emitIns_R_R_I(INS_addiw, EA_4BYTE, tempReg, lengthReg, 0); // sign-extend + GetEmitter()->emitIns_R_R(INS_sext_w, EA_4BYTE, tempReg, lengthReg); lengthReg = tempReg; } if (genActualType(index) == TYP_INT) { regNumber tempReg = internalRegisters.GetSingle(oper); - GetEmitter()->emitIns_R_R_I(INS_addiw, EA_4BYTE, tempReg, indexReg, 0); // sign-extend + GetEmitter()->emitIns_R_R(INS_sext_w, EA_4BYTE, tempReg, indexReg); indexReg = tempReg; } diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index e292e260ad99ab..f1451dc83ef2c1 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -588,7 +588,7 @@ void emitter::emitIns_R_R( { code_t code = emitInsCode(ins); - if (INS_mov == ins) + if (INS_mov == ins || INS_sext_w == ins) { assert(isGeneralRegisterOrR0(reg1)); assert(isGeneralRegisterOrR0(reg2)); @@ -3564,8 +3564,15 @@ void emitter::emitDispInsName( //} switch (opcode2) { - case 0x0: // ADDIW - printf("addiw %s, %s, %d\n", rd, rs1, imm12); + case 0x0: // ADDIW & SEXT.W + if (imm12 == 0) + { + printf("sext.w %s, %s\n", rd, rs1); + } + else + { + printf("addiw %s, %s, %d\n", rd, rs1, imm12); + } return; case 0x1: // SLLIW printf("slliw %s, %s, %d\n", rd, rs1, imm12 & 0x3f); // 6 BITS for SHAMT in RISCV64 @@ -4983,18 +4990,16 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, if (dstReg == regOp1) { assert(tempReg != regOp1); - assert(REG_RA != regOp1); saveOperReg1 = tempReg; - saveOperReg2 = regOp2; - emitIns_R_R_I(INS_addi, attr, tempReg, regOp1, 0); + saveOperReg2 = (regOp1 == regOp2) ? tempReg : regOp2; + emitIns_R_R(INS_mov, attr, tempReg, regOp1); } else if (dstReg == regOp2) { assert(tempReg != regOp2); - assert(REG_RA != regOp2); saveOperReg1 = regOp1; saveOperReg2 = tempReg; - emitIns_R_R_I(INS_addi, attr, tempReg, regOp2, 0); + emitIns_R_R(INS_mov, attr, tempReg, regOp2); } else { @@ -5005,73 +5010,84 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, emitIns_R_R_R(ins, attr, dstReg, regOp1, regOp2); + /* + Check if A = B + C + ADD : A = B + C + SUB : B = A - C + In case of addition: + dst = src1 + src2 + A = dst + B = src1 + C = src2 + In case of subtraction: + dst = src1 - src2 + src1 = dst + src2 + A = src1 + B = dst + C = src2 + */ if (needCheckOv) { - ssize_t imm; - regNumber tempReg1; - regNumber tempReg2; - // ADD : A = B + C - // SUB : C = A - B - bool isAdd = (dst->OperGet() == GT_ADD); + regNumber resultReg = REG_NA; + + if (dst->OperGet() == GT_ADD) + { + resultReg = dstReg; + regOp1 = saveOperReg1; + regOp2 = saveOperReg2; + } + else + { + resultReg = saveOperReg1; + regOp1 = dstReg; + regOp2 = saveOperReg2; + } + + instruction branchIns = INS_none; + regNumber branchReg1 = REG_NA; + regNumber branchReg2 = REG_NA; + if ((dst->gtFlags & GTF_UNSIGNED) != 0) { - // if A < B, goto overflow - if (isAdd) - { - tempReg1 = dstReg; - tempReg2 = saveOperReg1; - } - else - { - tempReg1 = saveOperReg1; - tempReg2 = saveOperReg2; - } - codeGen->genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bltu, tempReg1, nullptr, tempReg2); + // if A < B then overflow + branchIns = INS_bltu; + branchReg1 = resultReg; + branchReg2 = regOp1; } else { - tempReg1 = REG_RA; - tempReg2 = codeGen->internalRegisters.Extract(dst); - assert(tempReg1 != tempReg2); - assert(tempReg1 != saveOperReg1); - assert(tempReg2 != saveOperReg2); + regNumber tempReg1 = codeGen->internalRegisters.GetSingle(dst); - ssize_t ui6 = (attr == EA_4BYTE) ? 31 : 63; - emitIns_R_R_I(INS_srli, attr, tempReg1, isAdd ? saveOperReg1 : dstReg, ui6); - emitIns_R_R_I(INS_srli, attr, tempReg2, saveOperReg2, ui6); + branchIns = INS_bne; - emitIns_R_R_R(INS_xor, attr, tempReg1, tempReg1, tempReg2); if (attr == EA_4BYTE) { - imm = 1; - emitIns_R_R_I(INS_andi, attr, tempReg1, tempReg1, imm); - emitIns_R_R_I(INS_andi, attr, tempReg2, tempReg2, imm); - } - // if (B > 0 && C < 0) || (B < 0 && C > 0), skip overflow - BasicBlock* tmpLabel = codeGen->genCreateTempLabel(); - BasicBlock* tmpLabel2 = codeGen->genCreateTempLabel(); - BasicBlock* tmpLabel3 = codeGen->genCreateTempLabel(); - - emitIns_J_cond_la(INS_bne, tmpLabel, tempReg1, REG_R0); - - emitIns_J_cond_la(INS_bne, tmpLabel3, tempReg2, REG_R0); + assert(src1->gtType != TYP_LONG); + assert(src2->gtType != TYP_LONG); - // B > 0 and C > 0, if A < B, goto overflow - emitIns_J_cond_la(INS_bge, tmpLabel, isAdd ? dstReg : saveOperReg1, - isAdd ? saveOperReg1 : saveOperReg2); + emitIns_R_R_R(INS_add, attr, tempReg1, regOp1, regOp2); - codeGen->genDefineTempLabel(tmpLabel2); - - codeGen->genJumpToThrowHlpBlk(EJ_jmp, SCK_OVERFLOW); - - codeGen->genDefineTempLabel(tmpLabel3); + // if 64-bit addition is not equal to 32-bit addition for 32-bit operands then overflow + branchReg1 = resultReg; + branchReg2 = tempReg1; + } + else + { + assert(attr == EA_8BYTE); + assert(tempReg != tempReg1); + // When the tempReg2 is being used then the tempReg has to be already dead + regNumber tempReg2 = tempReg; - // B < 0 and C < 0, if A > B, goto overflow - emitIns_J_cond_la(INS_blt, tmpLabel2, isAdd ? saveOperReg1 : saveOperReg2, - isAdd ? dstReg : saveOperReg1); + emitIns_R_R_R(INS_slt, attr, tempReg1, resultReg, regOp1); + emitIns_R_R_I(INS_slti, attr, tempReg2, regOp2, 0); - codeGen->genDefineTempLabel(tmpLabel); + // if ((A < B) != (C < 0)) then overflow + branchReg1 = tempReg1; + branchReg2 = tempReg2; + } } + + codeGen->genJumpToThrowHlpBlk_la(SCK_OVERFLOW, branchIns, branchReg1, nullptr, branchReg2); } } break; diff --git a/src/coreclr/jit/instrsriscv64.h b/src/coreclr/jit/instrsriscv64.h index 3d8416d09e0473..281dacaeec5dce 100644 --- a/src/coreclr/jit/instrsriscv64.h +++ b/src/coreclr/jit/instrsriscv64.h @@ -36,6 +36,7 @@ INST(nop, "nop", 0, 0x00000013) //// R_R INST(mov, "mov", 0, 0x00000013) +INST(sext_w, "sext.w", 0, 0x0000001b) ////R_I INST(lui, "lui", 0, 0x00000037) From d51e6d0ecb357db5d5d5d3380ab4adcf5706f981 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 27 May 2024 08:35:20 -0700 Subject: [PATCH 02/12] =?UTF-8?q?Revert=20"=EF=BB=BFEnsure=20LoaderAllocat?= =?UTF-8?q?or=20can't=20be=20collected=20while=20we=20clean=20handles=20on?= =?UTF-8?q?=20=E2=80=A6"=20(#102729)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 35e4aad602ee3c28330e94746cfd4e0d4569b66f. --- src/coreclr/vm/loaderallocator.cpp | 4 +++- src/coreclr/vm/threadstatics.cpp | 21 ++++++--------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index dad12b8aa781fe..4f625e592e8d9e 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -964,11 +964,13 @@ void LoaderAllocator::SetHandleValue(LOADERHANDLE handle, OBJECTREF value) { NOTHROW; GC_NOTRIGGER; - MODE_COOPERATIVE; + MODE_ANY; PRECONDITION(handle != NULL); } CONTRACTL_END; + GCX_COOP(); + GCPROTECT_BEGIN(value); // If the slot value does have the low bit set, then it is a simple pointer to the value diff --git a/src/coreclr/vm/threadstatics.cpp b/src/coreclr/vm/threadstatics.cpp index aa9408a7791a6f..74d2eb08a3dc8d 100644 --- a/src/coreclr/vm/threadstatics.cpp +++ b/src/coreclr/vm/threadstatics.cpp @@ -52,22 +52,13 @@ void ThreadLocalBlock::FreeTLM(SIZE_T i, BOOL isThreadShuttingdown) ThreadLocalModule::CollectibleDynamicEntry *entry = (ThreadLocalModule::CollectibleDynamicEntry*)pThreadLocalModule->m_pDynamicClassTable[k].m_pDynamicEntry; PTR_LoaderAllocator pLoaderAllocator = entry->m_pLoaderAllocator; - // LoaderAllocator may be collected when the thread is shutting down. - // We enter coop mode to ensure that we get a valid value of the exposed object and - // can safely clean up handles if it is not yet collected. - GCX_COOP(); - - LOADERALLOCATORREF loaderAllocator = pLoaderAllocator->GetExposedObject(); - if (loaderAllocator != NULL) + if (entry->m_hGCStatics != 0) + { + pLoaderAllocator->FreeHandle(entry->m_hGCStatics); + } + if (entry->m_hNonGCStatics != 0) { - if (entry->m_hGCStatics != 0) - { - pLoaderAllocator->FreeHandle(entry->m_hGCStatics); - } - if (entry->m_hNonGCStatics != 0) - { - pLoaderAllocator->FreeHandle(entry->m_hNonGCStatics); - } + pLoaderAllocator->FreeHandle(entry->m_hNonGCStatics); } } delete pThreadLocalModule->m_pDynamicClassTable[k].m_pDynamicEntry; From 632238bcbf97780eeb8b734611322402ed6cfd88 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 17:56:25 +0200 Subject: [PATCH 03/12] Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240520.1 (#102723) Microsoft.SourceBuild.Intermediate.source-build-reference-packages From Version 9.0.0-alpha.1.24256.2 -> To Version 9.0.0-alpha.1.24270.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a37a86e442643e..9fde4018aacb7b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -79,9 +79,9 @@ - + https://github.com/dotnet/source-build-reference-packages - a4c02499bef24d0e16255657ccdb160d26c82c32 + 0df72d85186994facaefcb4eb832b8c8a8e5ae3d From 2feae23741a44e31e0e0de5d43e0a5919688505e Mon Sep 17 00:00:00 2001 From: Badre BSAILA <54767641+pedrobsaila@users.noreply.github.com> Date: Mon, 27 May 2024 20:38:42 +0200 Subject: [PATCH 04/12] Http2Connection throws misleading exceptions on ping timeouts (#102691) * Http2Connection throws misleading exceptions on ping timeouts * fix unwanted diffs 1 * fix unwanted diffs 2 * fix remarks --- src/libraries/System.Net.Http/src/Resources/Strings.resx | 5 ++++- .../System/Net/Http/SocketsHttpHandler/Http2Connection.cs | 2 +- .../SocketsHttpHandlerTest.Http2KeepAlivePing.cs | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx index ca69a570c984fc..6f80a984651855 100644 --- a/src/libraries/System.Net.Http/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx @@ -576,7 +576,10 @@ The HTTP/1.1 response chunk was too large. - + Failed to establish web socket connection over HTTP/2 because extended CONNECT is not supported. Try to downgrade the request version to HTTP/1.1. + + The HTTP/2 server didn't respond to a ping request within the configured KeepAlivePingDelay. + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index e91ccefff630f3..74b6fc84c3256b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -2136,7 +2136,7 @@ private void VerifyKeepAlive() break; case KeepAliveState.PingSent: if (now > _keepAlivePingTimeoutTimestamp) - ThrowProtocolError(); + ThrowProtocolError(Http2ProtocolErrorCode.ProtocolError, SR.net_ping_request_timed_out); break; default: Debug.Fail($"Unexpected keep alive state ({_keepAliveState})"); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs index a9beb393918b5c..0f1c1b8d58c326 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs @@ -197,6 +197,7 @@ await Http2LoopbackServer.CreateClientAndServerAsync(async uri => // The request should fail due to the connection being torn down due to KeepAlivePingTimeout. HttpProtocolException pex = Assert.IsType(ex.InnerException); Assert.Equal(HttpRequestError.HttpProtocolError, pex.HttpRequestError); + Assert.Contains("KeepAlivePingDelay", pex.Message); // Let connection live until server finishes: await _serverFinished.Task; From a71f19b802c68967b956c495c041ab64a69fdd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yn=C3=A8s=20Jaradin?= Date: Tue, 28 May 2024 00:11:38 +0200 Subject: [PATCH 05/12] ilasm support for methods with multiple documents (#102199) * ilasm support for methods with multiple documents Make sure the SequencePoints produced in the PDB reference the documents indicated on the .line directive. Fix #102198 * Clean up ilasm PortablePdb tests --------- Co-authored-by: Ivan Povazan --- src/coreclr/ilasm/assembler.cpp | 9 ++++ src/coreclr/ilasm/method.cpp | 2 + src/coreclr/ilasm/method.hpp | 2 + src/coreclr/ilasm/portable_pdb.cpp | 20 ++++++-- .../PortablePdb/IlasmPortablePdbTester.cs | 23 ++++++--- .../IlasmPortablePdbTesterCommon.cs | 49 +++++++++++-------- 6 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/coreclr/ilasm/assembler.cpp b/src/coreclr/ilasm/assembler.cpp index e105c00162c55c..4aa33378c0838c 100644 --- a/src/coreclr/ilasm/assembler.cpp +++ b/src/coreclr/ilasm/assembler.cpp @@ -1420,6 +1420,15 @@ void Assembler::EmitOpcode(Instr* instr) pLPC->PC = m_CurPC; pLPC->pOwnerDocument = instr->pOwnerDocument; + if(m_pCurMethod->m_FirstDocument == NULL) + { + m_pCurMethod->m_FirstDocument = instr->pOwnerDocument; + } + else if (instr->pOwnerDocument != NULL && m_pCurMethod->m_FirstDocument != instr->pOwnerDocument) + { + m_pCurMethod->m_HasMultipleDocuments = TRUE; + } + if (0xfeefee == instr->linenum && 0xfeefee == instr->linenum_end && 0 == instr->column && diff --git a/src/coreclr/ilasm/method.cpp b/src/coreclr/ilasm/method.cpp index c8946e7f80d78e..7fb5767b3bd2f4 100644 --- a/src/coreclr/ilasm/method.cpp +++ b/src/coreclr/ilasm/method.cpp @@ -35,6 +35,8 @@ Method::Method(Assembler *pAssembler, Class *pClass, _In_ __nullterminated char m_pbsBody = NULL; m_fNewBody = TRUE; m_fNew = TRUE; + m_FirstDocument = NULL; + m_HasMultipleDocuments = FALSE; // move the PInvoke descriptor (if any) from Assembler // (Assembler gets the descriptor BEFORE it calls new Method) diff --git a/src/coreclr/ilasm/method.hpp b/src/coreclr/ilasm/method.hpp index 4af091a0c5dcd6..8a0a1fd87293b4 100644 --- a/src/coreclr/ilasm/method.hpp +++ b/src/coreclr/ilasm/method.hpp @@ -337,6 +337,8 @@ class Method unsigned m_LineNum; // debug info LinePCList m_LinePCList; + Document* m_FirstDocument; + BOOL m_HasMultipleDocuments; // custom values CustomDescrList m_CustomDescrList; // token relocs (used for OBJ generation only) diff --git a/src/coreclr/ilasm/portable_pdb.cpp b/src/coreclr/ilasm/portable_pdb.cpp index 5e56e55eb716ed..68bd1bd72b950d 100644 --- a/src/coreclr/ilasm/portable_pdb.cpp +++ b/src/coreclr/ilasm/portable_pdb.cpp @@ -209,6 +209,7 @@ HRESULT PortablePdbWriter::DefineSequencePoints(Method* method) ULONG localSigRid = 0; ULONG offset = 0; ULONG deltaLines = 0; + ULONG currDocumentRid = 0; LONG deltaColumns = 0; LONG deltaStartLine = 0; LONG deltaStartColumn = 0; @@ -225,7 +226,11 @@ HRESULT PortablePdbWriter::DefineSequencePoints(Method* method) // LocalSignature localSigRid = RidFromToken(method->m_LocalsSig); CompressUnsignedLong(localSigRid, blob); - // InitialDocument TODO: skip this for now + currDocumentRid = RidFromToken(method->m_FirstDocument->GetToken()); + if(method->m_HasMultipleDocuments) + { + CompressUnsignedLong(currDocumentRid, blob); + } } // SequencePointRecord :: = sequence-point-record | hidden-sequence-point-record @@ -250,6 +255,15 @@ HRESULT PortablePdbWriter::DefineSequencePoints(Method* method) if (!currSeqPoint->IsHidden) { + //document + if(RidFromToken(currSeqPoint->pOwnerDocument->GetToken()) != currDocumentRid) + { + //document-record + currDocumentRid = RidFromToken(currSeqPoint->pOwnerDocument->GetToken()); + CompressUnsignedLong(0, blob); + CompressUnsignedLong(currDocumentRid, blob); + } + //offset offset = (i == 0) ? currSeqPoint->PC : currSeqPoint->PC - prevSeqPoint->PC; CompressUnsignedLong(offset, blob); @@ -311,8 +325,8 @@ HRESULT PortablePdbWriter::DefineSequencePoints(Method* method) // finally define sequence points for the method if ((isValid && currSeqPoint != NULL) || hasEmptyMethodBody) { - mdDocument document = hasEmptyMethodBody ? m_currentDocument->GetToken() : currSeqPoint->pOwnerDocument->GetToken(); - ULONG documentRid = RidFromToken(document); + mdDocument document = hasEmptyMethodBody ? m_currentDocument->GetToken() : method->m_FirstDocument->GetToken(); + ULONG documentRid = method->m_HasMultipleDocuments ? 0 : RidFromToken(document); hr = m_pdbEmitter->DefineSequencePoints(documentRid, blob->ptr(), blob->length()); } diff --git a/src/tests/ilasm/PortablePdb/IlasmPortablePdbTester.cs b/src/tests/ilasm/PortablePdb/IlasmPortablePdbTester.cs index d804dd63a0f4ca..e4089f9812e377 100644 --- a/src/tests/ilasm/PortablePdb/IlasmPortablePdbTester.cs +++ b/src/tests/ilasm/PortablePdb/IlasmPortablePdbTester.cs @@ -145,12 +145,14 @@ public void TestPortablePdbMethodDebugInformation1() // Tests whether the portable PDB has appropriate sequence points defined // The test source file includes external source reference and thus has 2 variants depending on OS type - [Fact] - public void TestPortablePdbMethodDebugInformation2() + [Theory] + [InlineData("TestMethodDebugInformation")] + [InlineData("TestDocuments1")] + public void TestPortablePdbMethodDebugInformation2(string testName) { - var ilSource = IsUnix ? "TestMethodDebugInformation_unix.il" : "TestMethodDebugInformation_win.il"; + var ilSource = testName + (IsUnix ? "_unix.il" : "_win.il"); - var expected = IlasmPortablePdbTesterCommon.GetExpectedForTestMethodDebugInformation(ilSource); + var expected = IlasmPortablePdbTesterCommon.GetExpectedForTestMethodDebugInformation(testName, IsUnix); var ilasm = IlasmPortablePdbTesterCommon.GetIlasmFullPath(CoreRootVar, IlasmFile); IlasmPortablePdbTesterCommon.Assemble(ilasm, ilSource, TestDir, out string dll, out string pdb); @@ -174,10 +176,17 @@ public void TestPortablePdbMethodDebugInformation2() // verify method debug information from portable pdb metadata var methodDebugInformation = portablePdbMdReader.GetMethodDebugInformation(methodDefinitionHandle); - var methodDocument = portablePdbMdReader.GetDocument(methodDebugInformation.Document); - var methodDocumentName = portablePdbMdReader.GetString(methodDocument.Name); - Assert.Equal(expectedMethodDbgInfo.Document.Name, methodDocumentName); + if (expectedMethodDbgInfo.Document == null) + { + Assert.True(methodDebugInformation.Document.IsNil); + } + else + { + var methodDocument = portablePdbMdReader.GetDocument(methodDebugInformation.Document); + var methodDocumentName = portablePdbMdReader.GetString(methodDocument.Name); + Assert.Equal(expectedMethodDbgInfo.Document.Name, methodDocumentName); + } int i = 0; foreach (var sequencePoint in methodDebugInformation.GetSequencePoints()) { diff --git a/src/tests/ilasm/PortablePdb/IlasmPortablePdbTesterCommon.cs b/src/tests/ilasm/PortablePdb/IlasmPortablePdbTesterCommon.cs index 1c535fc802478b..f31fb44f5f06b6 100644 --- a/src/tests/ilasm/PortablePdb/IlasmPortablePdbTesterCommon.cs +++ b/src/tests/ilasm/PortablePdb/IlasmPortablePdbTesterCommon.cs @@ -94,7 +94,7 @@ public static List GetExpectedDocuments(string testName, string te } } - public static Dictionary GetExpectedForTestMethodDebugInformation(string testName) + public static Dictionary GetExpectedForTestMethodDebugInformation(string testName, bool isUnix) { string method1; string method2; @@ -103,39 +103,38 @@ public static Dictionary GetExpectedForTestM switch (testName) { - case "TestMethodDebugInformation_unix.il": + case "TestMethodDebugInformation": method1 = ".ctor"; method2 = "Pow"; - document1 = new DocumentStub("/tmp/TestMethodDebugInformation/SimpleMath.cs"); - document2 = new DocumentStub("/tmp/TestMethodDebugInformation/SimpleMathMethods.cs"); + document1 = isUnix ? new DocumentStub("/tmp/TestMethodDebugInformation/SimpleMath.cs") : new DocumentStub("C:\\tmp\\TestMethodDebugInformation\\SimpleMath.cs"); + document2 = isUnix ? new DocumentStub("/tmp/TestMethodDebugInformation/SimpleMathMethods.cs") : new DocumentStub("C:\\tmp\\TestMethodDebugInformation\\SimpleMathMethods.cs"); break; - case "TestMethodDebugInformation_win.il": - method1 = ".ctor"; - method2 = "Pow"; - document1 = new DocumentStub("C:\\tmp\\TestMethodDebugInformation\\SimpleMath.cs"); - document2 = new DocumentStub("C:\\tmp\\TestMethodDebugInformation\\SimpleMathMethods.cs"); + case "TestDocuments1": + method1 = "Foo"; + method2 = null; + document1 = isUnix ? new DocumentStub("/tmp/non_existent_source1.cs") : new DocumentStub("C:\\tmp\\non_existent_source1.cs"); + document2 = isUnix ? new DocumentStub("/tmp/non_existent_source2.cs") : new DocumentStub("C:\\tmp\\non_existent_source2.cs"); break; default: Assert.Fail(); return null; } - return new Dictionary() + var result = new Dictionary(); + switch (testName) { - { - method1, - new MethodDebugInformationStub(method1, document1, + case "TestMethodDebugInformation": + result.Add(method1, + new MethodDebugInformationStub(method1, document1, new List() { new SequencePointStub(document1, false, 0x0, 6, 6, 9, 37), new SequencePointStub(document1, false, 0x7, 7, 7, 9, 10), new SequencePointStub(document1, false, 0x8, 8, 8, 13, 28), new SequencePointStub(document1, false, 0xf, 9, 9, 9, 10), - }) - }, - { - method2, - new MethodDebugInformationStub(method2, document2, + })); + result.Add(method2, + new MethodDebugInformationStub(method2, document2, new List() { new SequencePointStub(document2, false, 0x0, 6, 6, 9, 10), @@ -153,9 +152,19 @@ public static Dictionary GetExpectedForTestM new SequencePointStub(document2, true, 0x1e), new SequencePointStub(document2, false, 0x21, 15, 15, 13, 24), new SequencePointStub(document2, false, 0x26, 16, 16, 9, 10), - }) - } + })); + break; + case "TestDocuments1": + result.Add(method1, + new MethodDebugInformationStub(method1, null, + new List() + { + new SequencePointStub(document1, false, 0x0, 1, 1, 9, 10), + new SequencePointStub(document2, false, 0x1, 2, 2, 9, 10), + })); + break; }; + return result; } public static List GetExpectedForTestLocalScopes(string testName) From a50ba0669353893ca8ade8568b0a7d210b5a425f Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Tue, 28 May 2024 02:38:52 +0200 Subject: [PATCH 06/12] Conservative fix for struct stores in optRemoveRedundantZeroInits (#102580) --- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/compiler.hpp | 35 ++++++++++++++++ src/coreclr/jit/optimizer.cpp | 11 +---- .../JitBlue/Runtime_102577/Runtime_102577.cs | 42 +++++++++++++++++++ .../Runtime_102577/Runtime_102577.csproj | 13 ++++++ 5 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.csproj diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 428c817c751c78..76df03352c55a7 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6784,8 +6784,8 @@ class Compiler public: bool fgIsBigOffset(size_t offset); - bool IsValidLclAddr(unsigned lclNum, unsigned offset); + bool IsPotentialGCSafePoint(GenTree* tree) const; private: bool fgNeedReturnSpillTemp(); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 648e2acc65acdc..40458c51df36ce 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3190,6 +3190,41 @@ inline bool Compiler::IsValidLclAddr(unsigned lclNum, unsigned offset) return (offset < UINT16_MAX) && (offset < lvaLclExactSize(lclNum)); } +//------------------------------------------------------------------------ +// IsPotentialGCSafePoint: Can the given tree be effectively a gc safe point? +// +// Arguments: +// tree - the tree to check +// +// Return Value: +// True if the tree can be a gc safe point +// +inline bool Compiler::IsPotentialGCSafePoint(GenTree* tree) const +{ + if (((tree->gtFlags & GTF_CALL) != 0)) + { + // if this is not a No-GC helper + if (!tree->IsCall() || !emitter::emitNoGChelper(tree->AsCall()->GetHelperNum())) + { + // assume that we have a safe point. + return true; + } + } + + // TYP_STRUCT-typed stores might be converted into calls (with gc safe points) in Lower. + // This is quite a conservative fix as it's hard to prove Lower won't do it at this point. + if (tree->OperIsLocalStore()) + { + return tree->TypeIs(TYP_STRUCT); + } + if (tree->OperIs(GT_STORE_BLK)) + { + return true; + } + + return false; +} + /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 5c7b97b306bf47..1b028eca78b846 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -5916,17 +5916,8 @@ void Compiler::optRemoveRedundantZeroInits() Statement* next = stmt->GetNextStmt(); for (GenTree* const tree : stmt->TreeList()) { - if (((tree->gtFlags & GTF_CALL) != 0)) - { - // if this is not a No-GC helper - if (!tree->IsCall() || !emitter::emitNoGChelper(tree->AsCall()->GetHelperNum())) - { - // assume that we have a safe point. - hasGCSafePoint = true; - } - } - hasImplicitControlFlow |= hasEHSuccs && ((tree->gtFlags & GTF_EXCEPT) != 0); + hasGCSafePoint |= IsPotentialGCSafePoint(tree); switch (tree->gtOper) { diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.cs b/src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.cs new file mode 100644 index 00000000000000..9e3d82b0cff821 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using Xunit; + +// This takes the address of, gets the size of, or declares a pointer to a managed type +#pragma warning disable CS8500 + +public unsafe class Runtime_102577 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Problem(void* pDst, void* pSrc, object* pObj) + { + Unsafe.CopyBlock(pDst, pSrc, 1000); + StructWithManyObjs x = default; + if (pDst != null) + { + x.ObjFour = *pObj; + *(StructWithManyObjs*)pDst = x; + } + } + + private struct StructWithManyObjs + { + public object ObjOne; + public object ObjTwo; + public object ObjThree; + public object ObjFour; + public object ObjFive; + } + + [Fact] + public static void TestEntryPoint() + { + object x = null; + byte* p = stackalloc byte[1000]; + Random.Shared.NextBytes(new Span(p, 1000)); + Problem(p, p, &x); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.csproj new file mode 100644 index 00000000000000..9e9758ca6966ab --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_102577/Runtime_102577.csproj @@ -0,0 +1,13 @@ + + + + true + True + true + + + + + + + From eb841abadd8b038c905503a7cf9e914af74d63fb Mon Sep 17 00:00:00 2001 From: yurai007 Date: Tue, 28 May 2024 04:35:50 +0200 Subject: [PATCH 07/12] [RISC-V] Improve code generating resolve stub assembly (#102318) * [RISC-V] Improve code generating resolve stub assembly This change replaces magic numbers with proper offsetofs and use compile time asserts instead runtime ones. That should make developers life easier in case of debugging or changing resolve stubs assembly. * Move annotation and don't check same thing many times --- src/coreclr/vm/riscv64/virtualcallstubcpu.hpp | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp index 8372d5f0bc4c4b..2f39e4f313c58b 100644 --- a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp +++ b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp @@ -156,9 +156,9 @@ struct ResolveStub private: friend struct ResolveHolder; - const static int resolveEntryPointLen = 20; - const static int slowEntryPointLen = 4; - const static int failEntryPointLen = 9; + constexpr static int resolveEntryPointLen = 20; + constexpr static int slowEntryPointLen = 4; + constexpr static int failEntryPointLen = 9; DWORD _resolveEntryPoint[resolveEntryPointLen]; DWORD _slowEntryPoint[slowEntryPointLen]; @@ -226,10 +226,12 @@ struct ResolveHolder // addi t0, t0, -12 _stub._resolveEntryPoint[n++] = 0xff428293; + constexpr size_t entryPointsLen = ResolveStub::resolveEntryPointLen+ResolveStub::slowEntryPointLen+ResolveStub::failEntryPointLen; + constexpr size_t hashedTokenOffset = offsetof(ResolveStub, _hashedToken); // lw t6, 0(t0) #t6 = this._hashedToken - _stub._resolveEntryPoint[n++] = 0x0002af83 | (33 << 22); //(20+4+9)*4<<20; - _ASSERTE((ResolveStub::resolveEntryPointLen+ResolveStub::slowEntryPointLen+ResolveStub::failEntryPointLen) == 33); - _ASSERTE((33<<2) == (offsetof(ResolveStub, _hashedToken) -offsetof(ResolveStub, _resolveEntryPoint[0]))); + _stub._resolveEntryPoint[n++] = 0x0002af83 | (hashedTokenOffset << 20); + static_assert_no_msg(entryPointsLen << 2 == hashedTokenOffset); + static_assert_no_msg(offsetof(ResolveStub, _resolveEntryPoint[0]) == 0); // xor t1, t1, t6 _stub._resolveEntryPoint[n++] = 0x01f34333; @@ -241,10 +243,10 @@ struct ResolveHolder _stub._resolveEntryPoint[n++] = 0x00cfdf9b; // and t1, t1, t6 _stub._resolveEntryPoint[n++] = 0x01f37333; + constexpr size_t cacheAddressOffset = offsetof(ResolveStub, _cacheAddress); // ld t6, 0(t0) # t6 = this._cacheAddress - _stub._resolveEntryPoint[n++] = 0x0002bf83 | (36 << 22); //(20+4+9+1+2)*4<<20; - _ASSERTE((ResolveStub::resolveEntryPointLen+ResolveStub::slowEntryPointLen+ResolveStub::failEntryPointLen+1+2) == 36); - _ASSERTE((36<<2) == (offsetof(ResolveStub, _cacheAddress) -offsetof(ResolveStub, _resolveEntryPoint[0]))); + _stub._resolveEntryPoint[n++] = 0x0002bf83 | (cacheAddressOffset << 20); + static_assert_no_msg((entryPointsLen+1+2) << 2 == cacheAddressOffset); // add t1, t6, t1 _stub._resolveEntryPoint[n++] = 0x006f8333; // ld t1, 0(t1) # t1 = e = this._cacheAddress[i] @@ -252,10 +254,10 @@ struct ResolveHolder // ld t6, 0(t1) # t6 = Check mt == e.pMT; _stub._resolveEntryPoint[n++] = 0x00033f83 | ((offsetof(ResolveCacheElem, pMT) & 0xfff) << 20); + constexpr size_t tokenOffset = offsetof(ResolveStub, _token); // ld t2, 0(t0) # $t2 = this._token - _stub._resolveEntryPoint[n++] = 0x0002b383 | (38<<22);//(20+4+9+1+2+2)*4<<20; - _ASSERTE((ResolveStub::resolveEntryPointLen+ResolveStub::slowEntryPointLen+ResolveStub::failEntryPointLen+1+4) == 38); - _ASSERTE((38<<2) == (offsetof(ResolveStub, _token) -offsetof(ResolveStub, _resolveEntryPoint[0]))); + _stub._resolveEntryPoint[n++] = 0x0002b383 | (tokenOffset << 20); + static_assert_no_msg((entryPointsLen+1+4) << 2 == tokenOffset); // bne t6, t3, next _stub._resolveEntryPoint[n++] = 0x01cf9a63;// | PC_REL_OFFSET(_slowEntryPoint[0], n); @@ -288,19 +290,19 @@ struct ResolveHolder // auipc t0, 0 _stub._slowEntryPoint[0] = 0x00000297; // ld t6, 0(t0) # r21 = _resolveWorkerTarget; - _ASSERTE((0x14*4) == ((INT32)(offsetof(ResolveStub, _resolveWorkerTarget) - (offsetof(ResolveStub, _slowEntryPoint[0]))))); - _ASSERTE((ResolveStub::slowEntryPointLen + ResolveStub::failEntryPointLen+1+3*2) == 0x14); + static_assert_no_msg((0x14*4) == ((INT32)(offsetof(ResolveStub, _resolveWorkerTarget) - (offsetof(ResolveStub, _slowEntryPoint[0]))))); + static_assert_no_msg((ResolveStub::slowEntryPointLen + ResolveStub::failEntryPointLen+1+3*2) == 0x14); _stub._slowEntryPoint[1] = 0x0002bf83 | ((0x14 * 4) << 20); // ld t2, 0(t0) # t2 = this._token; _stub._slowEntryPoint[2] = 0x0002b383 | ((0x12 * 4) << 20); //(18*4=72=0x48)<<20 - _ASSERTE((ResolveStub::slowEntryPointLen+ResolveStub::failEntryPointLen+1+4)*4 == (0x12 * 4)); - _ASSERTE((0x12 * 4) == (offsetof(ResolveStub, _token) -offsetof(ResolveStub, _slowEntryPoint[0]))); + static_assert_no_msg((ResolveStub::slowEntryPointLen+ResolveStub::failEntryPointLen+1+4)*4 == (0x12 * 4)); + static_assert_no_msg((0x12 * 4) == (offsetof(ResolveStub, _token) -offsetof(ResolveStub, _slowEntryPoint[0]))); // jalr x0, t6, 0 _stub._slowEntryPoint[3] = 0x000f8067; - _ASSERTE(4 == ResolveStub::slowEntryPointLen); + static_assert_no_msg(4 == ResolveStub::slowEntryPointLen); // ResolveStub._failEntryPoint(a0:MethodToken, a1,.., a7, t5:IndirectionCellAndFlags) // { @@ -315,8 +317,8 @@ struct ResolveHolder _stub._failEntryPoint[0] = 0x00000297; // ld t1, 0(t0) # t1 = _pCounter; 0x2800000=((failEntryPointLen+1)*4)<<20. _stub._failEntryPoint[1] = 0x0002b303 | 0x2800000; - _ASSERTE((((ResolveStub::failEntryPointLen+1)*4)<<20) == 0x2800000); - _ASSERTE((0x2800000>>20) == ((INT32)(offsetof(ResolveStub, _pCounter) - (offsetof(ResolveStub, _failEntryPoint[0]))))); + static_assert_no_msg((((ResolveStub::failEntryPointLen+1)*4)<<20) == 0x2800000); + static_assert_no_msg((0x2800000>>20) == ((INT32)(offsetof(ResolveStub, _pCounter) - (offsetof(ResolveStub, _failEntryPoint[0]))))); // lw t6, 0(t1) _stub._failEntryPoint[2] = 0x00032f83; // addi t6, t6, -1 @@ -325,7 +327,7 @@ struct ResolveHolder // sw t6, 0(t1) _stub._failEntryPoint[4] = 0x01f32023; - _ASSERTE(SDF_ResolveBackPatch == 0x1); + static_assert_no_msg(SDF_ResolveBackPatch == 0x1); // ;; ori t5, t5, t6 >=0 ? SDF_ResolveBackPatch:0; // slti t6, t6, 0 _stub._failEntryPoint[5] = 0x000faf93; @@ -337,8 +339,8 @@ struct ResolveHolder // j _resolveEntryPoint // pc - 128 = pc + 4 - resolveEntryPointLen * 4 - slowEntryPointLen * 4 - failEntryPointLen * 4; _stub._failEntryPoint[8] = 0xf81ff06f; - _ASSERTE(9 == ResolveStub::failEntryPointLen); - _stub._pCounter = counterAddr; + static_assert_no_msg(9 == ResolveStub::failEntryPointLen); + _stub._pCounter = counterAddr; _stub._hashedToken = hashedToken << LOG2_PTRSIZE; _stub._cacheAddress = (size_t) cacheAddr; _stub._token = dispatchToken; From 03bc51f54dac5b8c7ba94ef798dfc93bfbbe6ef9 Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Mon, 27 May 2024 22:34:46 -0700 Subject: [PATCH 08/12] fix connect test extension (#102668) --- .../tests/FunctionalTests/SocketAsyncEventArgsTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs index 59f0dd8b5fa4c3..afd56dfcc9ef76 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketAsyncEventArgsTest.cs @@ -1098,10 +1098,11 @@ internal static void Connect(this Socket socket, EndPoint ep, Memory buffe saea.SetBuffer(buffer); saea.RemoteEndPoint = ep; saea.Completed += (_, __) => re.Set(); - if (!socket.ConnectAsync(saea)) + if (socket.ConnectAsync(saea)) { re.Wait(timeout); } + Assert.True(socket.Connected); } internal static Task ConnectAsync(this Socket socket, EndPoint ep, Memory buffer, CancellationToken cancellationToken = default) From e8e553bee6f0c842020434a333be488edacb45b5 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 12:54:07 +0200 Subject: [PATCH 09/12] Update dependencies from https://github.com/dotnet/arcade build 20240524.1 (#102744) Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.TargetFramework , Microsoft.DotNet.Build.Tasks.Templating , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.GenAPI , Microsoft.DotNet.GenFacades , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.SharedFramework.Sdk , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.XliffTasks , Microsoft.DotNet.XUnitAssert , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.XUnitExtensions From Version 9.0.0-beta.24272.5 -> To Version 9.0.0-beta.24274.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 84 +++++++++---------- eng/Versions.props | 32 +++---- eng/common/core-templates/job/job.yml | 52 ++++++------ .../core-templates/steps/source-build.yml | 1 + eng/common/cross/tizen-fetch.sh | 2 +- eng/common/dotnet-install.sh | 2 +- eng/common/templates-official/job/job.yml | 5 +- .../steps/publish-pipeline-artifacts.yml | 4 +- eng/common/templates/job/job.yml | 2 + eng/common/tools.sh | 4 +- global.json | 6 +- 11 files changed, 103 insertions(+), 91 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 9fde4018aacb7b..d8e1a53f19d852 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -92,87 +92,87 @@ - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 https://github.com/dotnet/runtime-assets @@ -332,9 +332,9 @@ https://github.com/dotnet/xharness 8478d1a9a531e6b1cd26fb8c86400e2efbb8f2f3 - + https://github.com/dotnet/arcade - 2001d73c8ff942331a73300ba61fa6164805b231 + 91fdecfe881902a109205279e023037692db4c11 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index d76d352b6b5081..d4df9e79163d2a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -83,22 +83,22 @@ 9.0.100-preview.5.24272.19 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 2.6.7-beta.24272.5 - 9.0.0-beta.24272.5 - 2.6.7-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 - 9.0.0-beta.24272.5 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 2.6.7-beta.24274.1 + 9.0.0-beta.24274.1 + 2.6.7-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 + 9.0.0-beta.24274.1 1.4.0 diff --git a/eng/common/core-templates/job/job.yml b/eng/common/core-templates/job/job.yml index dc3bd560a50e24..7df58527978bb9 100644 --- a/eng/common/core-templates/job/job.yml +++ b/eng/common/core-templates/job/job.yml @@ -200,29 +200,28 @@ jobs: publishArtifacts: false # Publish test results - - ${{ if and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')) }}: - - ${{ if eq(parameters.testResultsFormat, 'xunit') }}: - - task: PublishTestResults@2 - displayName: Publish XUnit Test Results - inputs: - testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() - - ${{ if eq(parameters.testResultsFormat, 'vstest') }}: - - task: PublishTestResults@2 - displayName: Publish TRX Test Results - inputs: - testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' - searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' - testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx - mergeTestResults: ${{ parameters.mergeTestResults }} - continueOnError: true - condition: always() + - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'xunit')) }}: + - task: PublishTestResults@2 + displayName: Publish XUnit Test Results + inputs: + testResultsFormat: 'xUnit' + testResultsFiles: '*.xml' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() + - ${{ if or(and(eq(parameters.enablePublishTestResults, 'true'), eq(parameters.testResultsFormat, '')), eq(parameters.testResultsFormat, 'vstest')) }}: + - task: PublishTestResults@2 + displayName: Publish TRX Test Results + inputs: + testResultsFormat: 'VSTest' + testResultsFiles: '*.trx' + searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' + testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx + mergeTestResults: ${{ parameters.mergeTestResults }} + continueOnError: true + condition: always() # gather artifacts - ${{ if ne(parameters.artifacts.publish, '') }}: @@ -246,6 +245,8 @@ jobs: SourceFolder: 'artifacts/log' Contents: '**' TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log' + continueOnError: true + condition: always() - ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}: - task: CopyFiles@2 @@ -254,6 +255,8 @@ jobs: SourceFolder: 'artifacts/log/$(_BuildConfig)' Contents: '**' TargetFolder: '$(Build.ArtifactStagingDirectory)/artifacts/log/$(_BuildConfig)' + continueOnError: true + condition: always() - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - task: CopyFiles@2 displayName: Gather buildconfiguration for build retry @@ -261,6 +264,7 @@ jobs: SourceFolder: '$(Build.SourcesDirectory)/eng/common/BuildConfiguration' Contents: '**' TargetFolder: '$(Build.ArtifactStagingDirectory)/eng/common/BuildConfiguration' - + continueOnError: true + condition: always() - ${{ each step in parameters.artifactPublishSteps }}: - ${{ step }} diff --git a/eng/common/core-templates/steps/source-build.yml b/eng/common/core-templates/steps/source-build.yml index bdd725b496f91b..bea5c41875f21d 100644 --- a/eng/common/core-templates/steps/source-build.yml +++ b/eng/common/core-templates/steps/source-build.yml @@ -123,6 +123,7 @@ steps: artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) continueOnError: true condition: succeededOrFailed() + sbomEnabled: false # we don't need SBOM for logs # Manually inject component detection so that we can ignore the source build upstream cache, which contains # a nupkg cache of input packages (a local feed). diff --git a/eng/common/cross/tizen-fetch.sh b/eng/common/cross/tizen-fetch.sh index c15c5066950d12..28936ceef3a716 100755 --- a/eng/common/cross/tizen-fetch.sh +++ b/eng/common/cross/tizen-fetch.sh @@ -7,7 +7,7 @@ fi Log() { - if [ $VERBOSE -ge $1 ]; then + if [ $VERBOSE -ge 1 ]; then echo ${@:2} fi } diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh index 7e69e3a9e24a79..a2fba4703806e7 100755 --- a/eng/common/dotnet-install.sh +++ b/eng/common/dotnet-install.sh @@ -82,7 +82,7 @@ if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then dotnetRoot="$dotnetRoot/$architecture" fi -InstallDotNet $dotnetRoot $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { +InstallDotNet "$dotnetRoot" $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { local exit_code=$? Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2 ExitWithExitCode $exit_code diff --git a/eng/common/templates-official/job/job.yml b/eng/common/templates-official/job/job.yml index 4724e9aaa80910..0c2928d5c799eb 100644 --- a/eng/common/templates-official/job/job.yml +++ b/eng/common/templates-official/job/job.yml @@ -23,6 +23,7 @@ jobs: displayName: 'Publish logs' continueOnError: true condition: always() + sbomEnabled: false # we don't need SBOM for logs - ${{ if eq(parameters.enablePublishBuildArtifacts, true) }}: - output: buildArtifacts @@ -32,13 +33,15 @@ jobs: ArtifactName: ${{ coalesce(parameters.enablePublishBuildArtifacts.artifactName, '$(Agent.Os)_$(Agent.JobName)' ) }} continueOnError: true condition: always() + sbomEnabled: false # we don't need SBOM for logs - ${{ if eq(parameters.enableBuildRetry, 'true') }}: - output: pipelineArtifact targetPath: '$(Build.ArtifactStagingDirectory)/artifacts/eng/common/BuildConfiguration' artifactName: 'BuildConfiguration' displayName: 'Publish build retry configuration' - continueOnError: true + continueOnError: true + sbomEnabled: false # we don't need SBOM for BuildConfiguration - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), eq(parameters.enableSbom, 'true')) }}: - output: pipelineArtifact diff --git a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml index d71eb0c7439862..172f9f0fdc9701 100644 --- a/eng/common/templates-official/steps/publish-pipeline-artifacts.yml +++ b/eng/common/templates-official/steps/publish-pipeline-artifacts.yml @@ -23,4 +23,6 @@ steps: ${{ if parameters.args.artifactName }}: artifactName: ${{ parameters.args.artifactName }} ${{ if parameters.args.properties }}: - properties: ${{ parameters.args.properties }} \ No newline at end of file + properties: ${{ parameters.args.properties }} + ${{ if parameters.args.sbomEnabled }}: + sbomEnabled: ${{ parameters.args.sbomEnabled }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 1cf9a6d48127b6..5920952c5ba694 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -37,6 +37,7 @@ jobs: displayName: 'Publish logs' continueOnError: true condition: always() + sbomEnabled: false # we don't need SBOM for logs - ${{ if ne(parameters.enablePublishBuildArtifacts, 'false') }}: - template: /eng/common/core-templates/steps/publish-build-artifacts.yml @@ -59,3 +60,4 @@ jobs: artifactName: 'BuildConfiguration' displayName: 'Publish build retry configuration' continueOnError: true + sbomEnabled: false # we don't need SBOM for BuildConfiguration diff --git a/eng/common/tools.sh b/eng/common/tools.sh index db64e298ff6314..a4f5d1b7761b44 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -438,7 +438,7 @@ function StopProcesses { } function MSBuild { - local args=$@ + local args=( "$@" ) if [[ "$pipelines_log" == true ]]; then InitializeBuildTool InitializeToolset @@ -473,7 +473,7 @@ function MSBuild { args+=( "-logger:$selectedPath" ) fi - MSBuild-Core ${args[@]} + MSBuild-Core "${args[@]}" } function MSBuild-Core { diff --git a/global.json b/global.json index 1d941dfd8c8936..47b58e55ba932b 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "9.0.100-preview.4.24267.66" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24272.5", - "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24272.5", - "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24272.5", + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24274.1", + "Microsoft.DotNet.Helix.Sdk": "9.0.0-beta.24274.1", + "Microsoft.DotNet.SharedFramework.Sdk": "9.0.0-beta.24274.1", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", "Microsoft.NET.Sdk.IL": "9.0.0-preview.5.24272.3" From 1fc1dd84f3ac84e22975c981098c0cc527f9c7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 28 May 2024 20:43:47 +0900 Subject: [PATCH 10/12] Revert "FB" (#102740) This reverts commit 122ac8fadb183047d33e8dc158469849a723551e. --- .../emit/DynMethodJumpStubTests/DynMethodJumpStubTests.cs | 2 +- .../emit/DynMethodJumpStubTests/DynMethodJumpStubTests.csproj | 2 ++ src/tests/CoreMangLib/system/span/SlowTailCallArgs.cs | 2 +- src/tests/CoreMangLib/system/span/SlowTailCallArgs.csproj | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.cs b/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.cs index 2ae25d0391460c..b429668d461ac5 100644 --- a/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.cs +++ b/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.cs @@ -10,7 +10,7 @@ public static class DynamicMethodJumpStubTests { - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] + [Fact] public static void TestEntryPoint() { DynamicMethodJumpStubTest(); diff --git a/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.csproj b/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.csproj index 434b851572da89..f60da6be697e82 100644 --- a/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.csproj +++ b/src/tests/CoreMangLib/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubTests.csproj @@ -5,6 +5,8 @@ 1 true + + true diff --git a/src/tests/CoreMangLib/system/span/SlowTailCallArgs.cs b/src/tests/CoreMangLib/system/span/SlowTailCallArgs.cs index 931df4c7bd835f..f8e44485fc9f10 100644 --- a/src/tests/CoreMangLib/system/span/SlowTailCallArgs.cs +++ b/src/tests/CoreMangLib/system/span/SlowTailCallArgs.cs @@ -9,7 +9,7 @@ public static class Program { - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsReflectionEmitSupported))] + [Fact] public static int TestEntryPoint() { bool allPassed = true; diff --git a/src/tests/CoreMangLib/system/span/SlowTailCallArgs.csproj b/src/tests/CoreMangLib/system/span/SlowTailCallArgs.csproj index 795851c18ed660..7e9b7b8fc1dcf1 100644 --- a/src/tests/CoreMangLib/system/span/SlowTailCallArgs.csproj +++ b/src/tests/CoreMangLib/system/span/SlowTailCallArgs.csproj @@ -5,6 +5,8 @@ true 1 true + + true From 000524990156daa48a4f2489d3e98847e8cc6d61 Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Tue, 28 May 2024 13:04:42 -0300 Subject: [PATCH 11/12] fix inspect gchandle (#102637) --- src/mono/mono/component/debugger-agent.c | 38 ++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index ce43d282177f95..81ea280734fdf8 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -3286,6 +3286,7 @@ dbg_path_get_basename (const char *filename) static GENERATE_TRY_GET_CLASS_WITH_CACHE (hidden_klass, "System.Diagnostics", "DebuggerHiddenAttribute") static GENERATE_TRY_GET_CLASS_WITH_CACHE (step_through_klass, "System.Diagnostics", "DebuggerStepThroughAttribute") static GENERATE_TRY_GET_CLASS_WITH_CACHE (non_user_klass, "System.Diagnostics", "DebuggerNonUserCodeAttribute") +static GENERATE_TRY_GET_CLASS_WITH_CACHE (intptr_klass, "System", "IntPtr") static void init_jit_info_dbg_attrs (MonoJitInfo *ji) @@ -5578,6 +5579,7 @@ decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *bu int ret = 0; if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) && !(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) && + !(t->type == MONO_TYPE_I && type == MONO_TYPE_I8) && !(type == VALUE_TYPE_ID_FIXED_ARRAY) && !(type == MDBGPROT_VALUE_TYPE_ID_NULL) && !(t->type == MONO_TYPE_U && type == MONO_TYPE_VALUETYPE) && @@ -5640,7 +5642,13 @@ decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *bu case MONO_TYPE_I: case MONO_TYPE_U: /* We send these as vtypes, so we get them back as such */ - g_assert (type == MONO_TYPE_VALUETYPE); + if (type == MONO_TYPE_I8) + { + ret += sizeof(guint64); + goto end; + } + else + g_assert (type == MONO_TYPE_VALUETYPE); /* Fall through */ handle_vtype: case MONO_TYPE_VALUETYPE: @@ -5697,6 +5705,7 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) && !(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) && + !(t->type == MONO_TYPE_I && type == MONO_TYPE_I8) && !(type == VALUE_TYPE_ID_FIXED_ARRAY) && !(t->type == MONO_TYPE_U && type == MONO_TYPE_VALUETYPE) && !(t->type == MONO_TYPE_PTR && type == MONO_TYPE_I8) && @@ -5769,8 +5778,31 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, break; case MONO_TYPE_I: case MONO_TYPE_U: - /* We send these as vtypes, so we get them back as such */ - g_assert (type == MONO_TYPE_VALUETYPE); + if (type == MONO_TYPE_I8) //sometimes we send as a PTR because it's a IntPtr then the debugger will send back as I8 + { + MonoClassField *f = NULL; + gpointer iter = NULL; + MonoClass *intptr_klass = mono_class_try_get_intptr_klass_class (); + while ((f = mono_class_get_fields_internal (intptr_klass, &iter))) { + if (G_UNLIKELY (!f->type)) { + ERROR_DECL(error); + mono_field_resolve_type (f, error); + mono_error_cleanup (error); + if (!f->type) + continue; + } + if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) + continue; + if (mono_field_is_deleted (f)) + continue; + guint8 * fieldAddr = mono_vtype_get_field_addr (addr, f); + *(gint64*)fieldAddr = decode_long (buf, &buf, limit); + } + *endbuf = buf; + return ERR_NONE; + } + else /* We send these as vtypes, so we get them back as such */ + g_assert (type == MONO_TYPE_VALUETYPE); /* Fall through */ handle_vtype: case MONO_TYPE_VALUETYPE: From 9daa4b41eb9f157e79eaf05e2f7451c9c8f6dbdc Mon Sep 17 00:00:00 2001 From: Jacob Bundgaard Date: Tue, 28 May 2024 18:13:32 +0200 Subject: [PATCH 12/12] Add support for primary constructors in LoggerMessageGenerator (#101660) * Add support for primary constructors in LoggerMessageGenerator * Get the primary constructor parameters types from the constructor symbol instead of from the semantic model * Prioritize fields over primary constructor parameters and ignore shadowed parameters when finding a logger * Make checking for primary constructors non-conditional on Roslyn version and simplify project setup * Reintroduce Roslyn 4.8 test project * Add info-level diagnostic for logger primary constructor parameters that are shadowed by field * Update list of diagnostics with new logging message generator diagnostic * Only add non-logger field names to set of shadowed names * Add comment explaining the use of the set of shadowed names with an example --- docs/project/list-of-diagnostics.md | 2 +- ...rosoft.Extensions.Logging.Abstractions.sln | 7 + .../gen/DiagnosticDescriptors.cs | 8 ++ .../gen/LoggerMessageGenerator.Parser.cs | 60 +++++++- .../gen/LoggerMessageGenerator.Roslyn4.0.cs | 2 +- .../gen/Resources/Strings.resx | 62 ++++---- .../gen/Resources/xlf/Strings.cs.xlf | 10 ++ .../gen/Resources/xlf/Strings.de.xlf | 10 ++ .../gen/Resources/xlf/Strings.es.xlf | 10 ++ .../gen/Resources/xlf/Strings.fr.xlf | 10 ++ .../gen/Resources/xlf/Strings.it.xlf | 10 ++ .../gen/Resources/xlf/Strings.ja.xlf | 10 ++ .../gen/Resources/xlf/Strings.ko.xlf | 10 ++ .../gen/Resources/xlf/Strings.pl.xlf | 10 ++ .../gen/Resources/xlf/Strings.pt-BR.xlf | 10 ++ .../gen/Resources/xlf/Strings.ru.xlf | 10 ++ .../gen/Resources/xlf/Strings.tr.xlf | 10 ++ .../gen/Resources/xlf/Strings.zh-Hans.xlf | 10 ++ .../gen/Resources/xlf/Strings.zh-Hant.xlf | 10 ++ ...LoggerFromPrimaryConstructor.generated.txt | 21 +++ ...eldAndFromPrimaryConstructor.generated.txt | 21 +++ .../LoggerMessageGeneratedCodeTests.cs | 37 ++++- .../LoggerMessageGeneratorEmitterTests.cs | 34 +++++ .../LoggerMessageGeneratorParserTests.cs | 136 ++++++++++++++++++ ....Logging.Generators.Roslyn4.8.Tests.csproj | 22 +++ .../TestClasses/MiscTestExtensions.cs | 24 ++++ 26 files changed, 533 insertions(+), 33 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerFromPrimaryConstructor.generated.txt create mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerInFieldAndFromPrimaryConstructor.generated.txt create mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn4.8.Tests.csproj diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 41d5a78f3f179b..76e734dea8660b 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -145,7 +145,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL | __`SYSLIB1024`__ | Argument is using the unsupported out parameter modifier | | __`SYSLIB1025`__ | Multiple logging methods cannot use the same event name within a class | | __`SYSLIB1026`__ | C# language version not supported by the logging source generator. | -| __`SYSLIB1027`__ | _`SYSLIB1001`-`SYSLIB1029` reserved for logging._ | +| __`SYSLIB1027`__ | Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field | | __`SYSLIB1028`__ | _`SYSLIB1001`-`SYSLIB1029` reserved for logging._ | | __`SYSLIB1029`__ | _`SYSLIB1001`-`SYSLIB1029` reserved for logging._ | | __`SYSLIB1030`__ | JsonSourceGenerator did not generate serialization metadata for type | diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln index 4064dd66cbf19b..27d405dd7a6cba 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln @@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Loggin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests", "tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests.csproj", "{1CB869A7-2EEC-4A53-9C33-DF9E0C75825B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn4.8.Tests", "tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Roslyn4.8.Tests.csproj", "{D6167506-0671-46A3-94E5-7A98032DCEC6}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibraryImportGenerator", "..\System.Runtime.InteropServices\gen\LibraryImportGenerator\LibraryImportGenerator.csproj", "{852D4E16-58C3-47C2-A6BC-A5B12B37209F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.SourceGeneration", "..\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj", "{6645D0C4-83D1-4426-B9CD-67096CB7A60F}" @@ -135,6 +137,10 @@ Global {F3186815-B9A5-455F-B0DF-E39D4235C24F}.Debug|Any CPU.Build.0 = Debug|Any CPU {F3186815-B9A5-455F-B0DF-E39D4235C24F}.Release|Any CPU.ActiveCfg = Release|Any CPU {F3186815-B9A5-455F-B0DF-E39D4235C24F}.Release|Any CPU.Build.0 = Release|Any CPU + {D6167506-0671-46A3-94E5-7A98032DCEC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6167506-0671-46A3-94E5-7A98032DCEC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6167506-0671-46A3-94E5-7A98032DCEC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6167506-0671-46A3-94E5-7A98032DCEC6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -162,6 +168,7 @@ Global {8215F79E-510B-4CA1-B775-50C47BB58360} = {58760833-B4F5-429D-9ABD-15FDF83E25CD} {F3186815-B9A5-455F-B0DF-E39D4235C24F} = {14DFA192-3C7E-4F10-B5FD-3953BC82A6B1} {14DFA192-3C7E-4F10-B5FD-3953BC82A6B1} = {58760833-B4F5-429D-9ABD-15FDF83E25CD} + {D6167506-0671-46A3-94E5-7A98032DCEC6} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {450DA749-CBDC-4BDC-950F-8A491CF59D49} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs index 409ab6de3f51c9..a8f2af180720a2 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/DiagnosticDescriptors.cs @@ -208,5 +208,13 @@ public static class DiagnosticDescriptors category: "LoggingGenerator", defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); + + public static DiagnosticDescriptor PrimaryConstructorParameterLoggerHidden { get; } = DiagnosticDescriptorHelper.Create( + id: "SYSLIB1027", + title: new LocalizableResourceString(nameof(SR.PrimaryConstructorParameterLoggerHiddenTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)), + messageFormat: new LocalizableResourceString(nameof(SR.PrimaryConstructorParameterLoggerHiddenMessage), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Logging.Generators.SR)), + category: "LoggingGenerator", + DiagnosticSeverity.Info, + isEnabledByDefault: true); } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs index 1604b8689d97c5..b474c5ea54a150 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs @@ -630,11 +630,23 @@ private static string GenerateClassName(TypeDeclarationSyntax typeDeclaration) INamedTypeSymbol? classType = sm.GetDeclaredSymbol(classDec, _cancellationToken); + INamedTypeSymbol? currentClassType = classType; bool onMostDerivedType = true; - while (classType is { SpecialType: not SpecialType.System_Object }) + // We keep track of the names of all non-logger fields, since they prevent referring to logger + // primary constructor parameters with the same name. Example: + // partial class C(ILogger logger) + // { + // private readonly object logger = logger; + // + // [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + // public partial void M1(); // The ILogger primary constructor parameter cannot be used here. + // } + HashSet shadowedNames = new(StringComparer.Ordinal); + + while (currentClassType is { SpecialType: not SpecialType.System_Object }) { - foreach (IFieldSymbol fs in classType.GetMembers().OfType()) + foreach (IFieldSymbol fs in currentClassType.GetMembers().OfType()) { if (!onMostDerivedType && fs.DeclaredAccessibility == Accessibility.Private) { @@ -651,10 +663,52 @@ private static string GenerateClassName(TypeDeclarationSyntax typeDeclaration) return (null, true); } } + else + { + shadowedNames.Add(fs.Name); + } } onMostDerivedType = false; - classType = classType.BaseType; + currentClassType = currentClassType.BaseType; + } + + // We prioritize fields over primary constructor parameters and avoid warnings if both exist. + if (loggerField is not null) + { + return (loggerField, false); + } + + IEnumerable primaryConstructors = classType.InstanceConstructors + .Where(ic => ic.DeclaringSyntaxReferences + .Any(ds => ds.GetSyntax() is ClassDeclarationSyntax)); + + foreach (IMethodSymbol primaryConstructor in primaryConstructors) + { + foreach (IParameterSymbol parameter in primaryConstructor.Parameters) + { + if (IsBaseOrIdentity(parameter.Type, loggerSymbol)) + { + if (shadowedNames.Contains(parameter.Name)) + { + // Accessible fields always shadow primary constructor parameters, + // so we can't use the primary constructor parameter, + // even if the field is not a valid logger. + Diag(DiagnosticDescriptors.PrimaryConstructorParameterLoggerHidden, parameter.Locations[0], classDec.Identifier.Text); + + continue; + } + + if (loggerField == null) + { + loggerField = parameter.Name; + } + else + { + return (null, true); + } + } + } } return (loggerField, false); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs index 7dd80ba2926bf1..74cc8e13fcf0ef 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs @@ -45,7 +45,7 @@ private static void Execute(Compilation compilation, ImmutableArray distinctClasses = classes.Distinct(); + ImmutableHashSet distinctClasses = classes.ToImmutableHashSet(); var p = new Parser(compilation, context.ReportDiagnostic, context.CancellationToken); IReadOnlyList logClasses = p.GetLogClasses(distinctClasses); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx index 602e6f4730d216..cca9ce4ef6c0e0 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/Strings.resx @@ -1,17 +1,17 @@ - @@ -237,4 +237,12 @@ The Logging source generator is not available in C# {0}. Please use language version {1} or greater. + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf index 6f3218ac6dd5b7..eb8dd19b8c71a1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.cs.xlf @@ -132,6 +132,16 @@ Našlo se několik polí typu Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Odeberte redundantní kvalifikátor (Informace:, Upozornění:, Chyba: atd.) ze zprávy o protokolování, protože je na zadané úrovni protokolu implicitní. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf index b838765022a4ea..b508628ac5ec47 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.de.xlf @@ -132,6 +132,16 @@ Mehrere Felder vom Typ "Microsoft.Extensions.Logging.ILogger" gefunden {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Entfernen Sie den redundanten Qualifizierer (z. B. "Info:", "Warnung:" oder "Fehler:") aus der Protokollierungsmeldung, weil er auf der angegebenen Protokollebene implizit enthalten ist. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf index 30000484775d0a..fd199f459d96aa 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.es.xlf @@ -132,6 +132,16 @@ Se encontraron varios campos de tipo Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Quitar calificadores redundantes (Información:, Advertencia:, Error:, etc.) del mensaje de registro, ya que está implícito en el nivel de registro especificado. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf index 04ccccc8536aa0..ac019c9dabf7c9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.fr.xlf @@ -132,6 +132,16 @@ Plusieurs champs de type Microsoft.Extensions.Logging.ILogger ont été trouvés {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Supprimez le qualificateur redondant (Info:, Warning:, Error:, etc.) du message de journalisation, car il est implicite dans le niveau de journalisation spécifié. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf index 0c007fdce54828..dc2f02184e1b60 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.it.xlf @@ -132,6 +132,16 @@ Sono stati trovati più campi di tipo Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Rimuovere il qualificatore ridondante (Informazioni:, Avviso:, Errore: e così via) dal messaggio di registrazione perché è implicito nel livello di log specificato. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf index 36f5b1baad528f..3f0127050182cb 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ja.xlf @@ -132,6 +132,16 @@ Microsoft.Extensions.Logging.ILogger という種類の複数のフィールドが見つかりました {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. 指定されたログ レベルでは暗黙的であるため、冗長な修飾子 (Info:、Warning:、Error: など) をログ メッセージから削除します。 diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf index 547c49b3e33dc9..5bb9507b8591c1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ko.xlf @@ -132,6 +132,16 @@ Microsoft.Extensions.Logging.ILogger 형식의 필드가 여러 개 있음 {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. 중복 한정자(정보:, 경고:, 오류: 등)가 지정된 로그 수준에서 암시적이기 때문에 로깅 메시지에서 제거합니다. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf index a40b72d24ffcea..0c014dd5317e0e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pl.xlf @@ -132,6 +132,16 @@ Znaleziono wiele pól typu Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Usuń nadmiarowy kwalifikator (Info:, Warning:, Error: itp.) z komunikatu rejestrowania, ponieważ jest on domyślny na określonym poziomie dziennika. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf index 0560fb6b5907c8..6a4a35d1acc52b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.pt-BR.xlf @@ -132,6 +132,16 @@ Múltiplos campos encontrados do tipo Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Remova o qualificador redundante (Info:, Aviso:, Erro:, etc) da mensagem de log, pois está implícito no nível de log especificado. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf index 589635d5721bb9..053970d8886038 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.ru.xlf @@ -132,6 +132,16 @@ Обнаружено несколько полей типа Microsoft.Extensions.Logging.ILogger {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Удалите избыточный квалификатор (Info:, Warning:, Error:, и т. п.) из сообщения журнала, поскольку квалификатор подразумевается на указанном уровне ведения журнала. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf index c40d99aa4602c5..03f094a1607380 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.tr.xlf @@ -132,6 +132,16 @@ Microsoft.Extensions.Logging.ILogger türünde birden çok alan bulundu {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. Belirtilen günlük düzeyinde örtük olduğundan gereksiz niteleyiciyi (Bilgi:, Uyarı:, Hata: vb.) günlüğe kaydetme iletisinden kaldırın. diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf index 04c39c8843a1e1..2217d0a4cc9887 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hans.xlf @@ -132,6 +132,16 @@ 找到 Microsoft.Extensions.Logging.ILogger 类型的多个字段 {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. 从日志记录消息中删除冗余限定符(信息:、警告:、错误: 等),因为其在指定的日志级别中为隐式内容。 diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf index af008cf098ff8a..6044c601d92513 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Resources/xlf/Strings.zh-Hant.xlf @@ -132,6 +132,16 @@ 找到多個 Microsoft.Extensions.Logging.ILogger 類型的欄位 {Locked="Microsoft.Extensions.Logging.ILogger"} + + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + Class '{0}' has a primary constructor parameter of type Microsoft.Extensions.Logging.ILogger that is hidden by a field in the class or a base class, preventing its use + {Locked="Microsoft.Extensions.Logging.ILogger"} + + + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + Primary constructor parameter of type Microsoft.Extensions.Logging.ILogger is hidden by a field + {Locked="Microsoft.Extensions.Logging.ILogger"} + Remove redundant qualifier (Info:, Warning:, Error:, etc) from the logging message since it is implicit in the specified log level. 從記錄訊息中移除備援限定詞 (資訊:、警告:、錯誤: 等等),因為它在指定的記錄層級中為隱含。 diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerFromPrimaryConstructor.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerFromPrimaryConstructor.generated.txt new file mode 100644 index 00000000000000..ba6b0d865e6bf4 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerFromPrimaryConstructor.generated.txt @@ -0,0 +1,21 @@ +// +#nullable enable + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + partial class TestWithLoggerFromPrimaryConstructor + { + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] + private static readonly global::System.Action __M0Callback = + global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] + public partial void M0() + { + if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Debug)) + { + __M0Callback(logger, null); + } + } + } +} \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerInFieldAndFromPrimaryConstructor.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerInFieldAndFromPrimaryConstructor.generated.txt new file mode 100644 index 00000000000000..acfd43a0d287b4 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithLoggerInFieldAndFromPrimaryConstructor.generated.txt @@ -0,0 +1,21 @@ +// +#nullable enable + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + partial class TestWithLoggerFromPrimaryConstructor + { + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] + private static readonly global::System.Action __M0Callback = + global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] + public partial void M0() + { + if (_logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Debug)) + { + __M0Callback(_logger, null); + } + } + } +} \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs index 7688e26ad0062a..1013af8ae36722 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs @@ -26,7 +26,7 @@ public void FindsLoggerFieldInBaseClass() } [Fact] - public void FindsLoggerFieldInAnotherParialClass() + public void FindsLoggerFieldInAnotherPartialClass() { var logger = new MockLogger(); @@ -36,6 +36,41 @@ public void FindsLoggerFieldInAnotherParialClass() Assert.Equal("Test.", logger.LastFormattedString); } +#if ROSLYN4_8_OR_GREATER + [Fact] + public void FindsLoggerInPrimaryConstructorParameter() + { + var logger = new MockLogger(); + + logger.Reset(); + + new ClassWithPrimaryConstructor(logger).Test(); + Assert.Equal("Test.", logger.LastFormattedString); + } + + [Fact] + public void FindsLoggerInPrimaryConstructorParameterInDifferentPartialDeclaration() + { + var logger = new MockLogger(); + + logger.Reset(); + + new ClassWithPrimaryConstructorInDifferentPartialDeclaration(logger).Test(); + Assert.Equal("Test.", logger.LastFormattedString); + } + + [Fact] + public void FindsLoggerInFieldInitializedFromPrimaryConstructorParameter() + { + var logger = new MockLogger(); + + logger.Reset(); + + new ClassWithPrimaryConstructor(logger).Test(); + Assert.Equal("Test.", logger.LastFormattedString); + } +#endif + [Fact] public void BasicTests() { diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs index 30cf036fdd8606..0952f66a8adabb 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs @@ -187,6 +187,40 @@ public sealed class BarAttribute : Attribute { } await VerifyAgainstBaselineUsingFile("TestWithNestedClassWithGenericTypesWithAttributes.generated.txt", testSourceCode); } +#if ROSLYN4_8_OR_GREATER + [Fact] + public async Task TestBaseline_TestWithLoggerFromPrimaryConstructor_Success() + { + string testSourceCode = @" +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal partial class TestWithLoggerFromPrimaryConstructor(ILogger logger) + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M0"")] + public partial void M0(); + } +}"; + await VerifyAgainstBaselineUsingFile("TestWithLoggerFromPrimaryConstructor.generated.txt", testSourceCode); + } + + [Fact] + public async Task TestBaseline_TestWithLoggerInFieldAndFromPrimaryConstructor_UsesField() + { + string testSourceCode = @" +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal partial class TestWithLoggerFromPrimaryConstructor(ILogger logger) + { + private readonly ILogger _logger = logger; + + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M0"")] + public partial void M0(); + } +}"; + await VerifyAgainstBaselineUsingFile("TestWithLoggerInFieldAndFromPrimaryConstructor.generated.txt", testSourceCode); + } +#endif + [Fact] public void GenericTypeParameterAttributesAreRetained() { diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs index d0d5fc30af573f..15a4f965074775 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs @@ -417,6 +417,142 @@ internal partial class Logger } #endif + [Fact] + public async Task FieldOnOtherPartialDeclarationOK() + { + IReadOnlyList diagnostics = await RunGenerator(@" + partial class C + { + private ILogger _logger; + + public C(ILogger logger) + { + _logger = logger; + } + } + + partial class C + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + public partial void M1(); + } + "); + + Assert.Empty(diagnostics); + } + +#if ROSLYN4_8_OR_GREATER + [Fact] + public async Task PrimaryConstructorOK() + { + IReadOnlyList diagnostics = await RunGenerator(@" + partial class C(ILogger logger) + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + public partial void M1(); + } + "); + + Assert.Empty(diagnostics); + } + + [Fact] + public async Task PrimaryConstructorOnOtherPartialDeclarationOK() + { + IReadOnlyList diagnostics = await RunGenerator(@" + partial class C(ILogger logger); + + partial class C + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + public partial void M1(); + } + "); + + Assert.Empty(diagnostics); + } + + [Fact] + public async Task PrimaryConstructorWithDifferentNameLoggerFieldOK() + { + IReadOnlyList diagnostics = await RunGenerator(@" + partial class C(ILogger logger) + { + private readonly ILogger _logger = logger; + + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + public partial void M1(); + } + "); + + Assert.Empty(diagnostics); + } + + [Fact] + public async Task PrimaryConstructorWithSameNameLoggerFieldOK() + { + IReadOnlyList diagnostics = await RunGenerator(@" + partial class C(ILogger logger) + { + private readonly ILogger logger = logger; + + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + public partial void M1(); + } + "); + + Assert.Empty(diagnostics); + } + + [Fact] + public async Task PrimaryConstructorLoggerShadowedByField() + { + IReadOnlyList diagnostics = await RunGenerator(@" + partial class C(ILogger logger) + { + private readonly object logger = logger; + + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + public partial void M1(); + } + "); + + Assert.Equal(2, diagnostics.Count); + + Assert.Equal(DiagnosticDescriptors.PrimaryConstructorParameterLoggerHidden.Id, diagnostics[0].Id); + var lineSpan = diagnostics[0].Location.GetLineSpan(); + Assert.Equal(4, lineSpan.StartLinePosition.Line); + Assert.Equal(40, lineSpan.StartLinePosition.Character); + + Assert.Equal(DiagnosticDescriptors.MissingLoggerField.Id, diagnostics[1].Id); + } + + [Fact] + public async Task PrimaryConstructorLoggerShadowedByBaseClass() + { + IReadOnlyList diagnostics = await RunGenerator(@" + class Base(object logger) { + protected readonly object logger = logger; + } + + partial class Derived(ILogger logger) : Base(logger) + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")] + public partial void M1(); + } + "); + + Assert.Equal(2, diagnostics.Count); + + Assert.Equal(DiagnosticDescriptors.PrimaryConstructorParameterLoggerHidden.Id, diagnostics[0].Id); + var lineSpan = diagnostics[0].Location.GetLineSpan(); + Assert.Equal(8, lineSpan.StartLinePosition.Line); + Assert.Equal(46, lineSpan.StartLinePosition.Character); + + Assert.Equal(DiagnosticDescriptors.MissingLoggerField.Id, diagnostics[1].Id); + } +#endif + [Theory] [InlineData("false")] [InlineData("true")] diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn4.8.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn4.8.Tests.csproj new file mode 100644 index 00000000000000..e480e542b15444 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn4.8.Tests.csproj @@ -0,0 +1,22 @@ + + + + $(MicrosoftCodeAnalysisVersion_4_8) + $(DefineConstants);ROSLYN4_0_OR_GREATER;ROSLYN4_8_OR_GREATER + true + -O1 + + false + + + + + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/MiscTestExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/MiscTestExtensions.cs index 05984d67570bc2..5f4fec36ac7b77 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/MiscTestExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/MiscTestExtensions.cs @@ -57,6 +57,30 @@ public partial class PartialClassWithLoggerField public partial void Test(); } +#if ROSLYN4_8_OR_GREATER +public partial class ClassWithPrimaryConstructor(ILogger logger) +{ + [LoggerMessage(0, LogLevel.Debug, "Test.")] + public partial void Test(); +} + +public partial class ClassWithPrimaryConstructorInDifferentPartialDeclaration(ILogger logger); + +public partial class ClassWithPrimaryConstructorInDifferentPartialDeclaration +{ + [LoggerMessage(0, LogLevel.Debug, "Test.")] + public partial void Test(); +} + +public partial class ClassWithPrimaryConstructorAndField(ILogger logger) +{ + private readonly ILogger _logger = logger; + + [LoggerMessage(0, LogLevel.Debug, "Test.")] + public partial void Test(); +} +#endif + // Used to test use outside of a namespace internal static partial class NoNamespace {