diff --git a/src/MCP-Tests/MCPToolMethodMutationTest.class.st b/src/MCP-Tests/MCPToolMethodMutationTest.class.st index 08a02e5..9563cb1 100644 --- a/src/MCP-Tests/MCPToolMethodMutationTest.class.st +++ b/src/MCP-Tests/MCPToolMethodMutationTest.class.st @@ -928,8 +928,10 @@ MCPToolMethodMutationTest >> testCompileReturnsStructuredCommandErrorForSyntaxEr self assert: (error at: #errorCode) equals: 'CompileSyntaxError'. self assert: (error at: #className) equals: MCPToolMethodMutationTestTarget name. self assert: (error at: #classSide) equals: false. - self assert: (error at: #protocol) equals: 'tests'. - self assert: (error includesKey: #position). + self assert: (error at: #position) equals: 19. + self assert: (error at: #line) equals: 1. + self assert: (error at: #column) equals: 19. + self assert: (error at: #sourceLine) equals: 'brokenMethod ^ 1 +'. self deny: (error includesKey: #variableName). self deny: (MCPToolMethodMutationTestTarget includesSelector: #brokenMethod) ] @@ -954,10 +956,12 @@ MCPToolMethodMutationTest >> testCompileReturnsStructuredCommandErrorForUndeclar self assert: (self expectedUndeclaredVariableNoticeClassNames includes: (error at: #causeClass)). self assert: (error at: #className) equals: MCPToolMethodMutationTestTarget name. self assert: (error at: #classSide) equals: false. - self assert: (error at: #protocol) equals: 'tests'. self assert: (error at: #selector) equals: 'brokenMethod'. self assert: (error at: #variableName) equals: 'missingVar'. self assert: (error at: #position) equals: 16. + self assert: (error at: #line) equals: 1. + self assert: (error at: #column) equals: 16. + self assert: (error at: #sourceLine) equals: 'brokenMethod ^ missingVar'. self assert: ((error at: #message) includesSubstring: 'missingVar'). self deny: (MCPToolMethodMutationTestTarget includesSelector: #brokenMethod) ] diff --git a/src/MCP/MCPCompileMethodCommand.class.st b/src/MCP/MCPCompileMethodCommand.class.st index 3acaec3..46b0800 100644 --- a/src/MCP/MCPCompileMethodCommand.class.st +++ b/src/MCP/MCPCompileMethodCommand.class.st @@ -30,11 +30,15 @@ MCPCompileMethodCommand >> execute [ work: [ behavior := self tool behaviorNamed: self request className classSide: self request classSide. methodSource := self request methodSource withInternalLineEndings. - selector := self selectorForMethodSource: methodSource. + selector := [ self selectorForMethodSource: methodSource ] + on: Exception + do: [ :error | self signalCompileFailure: error methodSource: methodSource ]. changeKind := (behavior includesSelector: selector) ifTrue: [ 'replaced' ] ifFalse: [ 'created' ]. - selector := behavior compile: methodSource classified: self request protocol. + selector := [ behavior compile: methodSource classified: self request protocol ] + on: Exception + do: [ :error | self signalCompileFailure: error methodSource: methodSource ]. compiledMethod := self tool reformattedMethodForBehavior: behavior selector: selector. methodReference := self tool methodReferenceForBehavior: behavior selector: selector. result := MCPMethodCompileResult @@ -58,3 +62,16 @@ MCPCompileMethodCommand >> selectorForMethodSource: methodSourceString [ self tool signalBlockingCritiquesForMethodNode: methodNode. ^ methodNode selector ] + +{ #category : 'private - errors' } +MCPCompileMethodCommand >> signalCompileFailure: anError methodSource: methodSource [ + + anError mcpCommandErrorDo: [ :commandError | commandError signal ] otherwise: [ :compileError | + (self tool + commandErrorForCompileFailure: compileError + methodSource: methodSource + requestedContext: self request requestedContext + summary: + (self tool failureMessageForCompileClassNamed: self request className classSide: self request classSide error: compileError)) + signal ] +] diff --git a/src/MCP/MCPMethodCompileRequest.class.st b/src/MCP/MCPMethodCompileRequest.class.st index 54a52c0..447d99e 100644 --- a/src/MCP/MCPMethodCompileRequest.class.st +++ b/src/MCP/MCPMethodCompileRequest.class.st @@ -79,6 +79,5 @@ MCPMethodCompileRequest >> requestedContext [ ^ { (#className -> self className). - (#classSide -> self classSide). - (#protocol -> self protocol) } asDictionary + (#classSide -> self classSide) } asDictionary ] diff --git a/src/MCP/MCPToolMethodMutation.class.st b/src/MCP/MCPToolMethodMutation.class.st index 91efb4d..197d8ab 100644 --- a/src/MCP/MCPToolMethodMutation.class.st +++ b/src/MCP/MCPToolMethodMutation.class.st @@ -25,6 +25,12 @@ MCPToolMethodMutation class >> isAbstract [ ^ self = MCPToolMethodMutation ] +{ #category : 'private - errors' } +MCPToolMethodMutation >> addCompileSourceContextFor: methodSource to: details [ + + details at: #position ifPresent: [ :position | self addSourceLineContextFor: methodSource position: position to: details ] +] + { #category : 'private - refactoring' } MCPToolMethodMutation >> addParameterRefactoringForSelector: oldSelectorSymbol inBehavior: aBehavior to: newSelectorSymbol permutation: permutation newArgs: newArguments model: refactoringModel [ @@ -37,6 +43,24 @@ MCPToolMethodMutation >> addParameterRefactoringForSelector: oldSelectorSymbol i newArgs: newArguments ] +{ #category : 'private - errors' } +MCPToolMethodMutation >> addSourceLineContextFor: methodSource position: position to: details [ + + | boundedPosition column lineEnd lineNumber lineStart sourceLine sourceText | + sourceText := methodSource ifNil: [ '' ] ifNotNil: [ methodSource asString ]. + sourceText isEmpty ifTrue: [ ^ self ]. + boundedPosition := (position max: 1) min: sourceText size + 1. + lineStart := sourceText lastIndexOf: Character cr startingAt: boundedPosition - 1 ifAbsent: [ 0 ]. + lineEnd := sourceText indexOf: Character cr startingAt: boundedPosition ifAbsent: [ sourceText size + 1 ]. + lineNumber := (sourceText copyFrom: 1 to: lineStart) occurrencesOf: Character cr. + column := boundedPosition - lineStart. + sourceLine := sourceText copyFrom: lineStart + 1 to: lineEnd - 1. + details + at: #line put: lineNumber + 1; + at: #column put: column; + at: #sourceLine put: sourceLine +] + { #category : 'metadata' } MCPToolMethodMutation >> additionalKeywords [ @@ -104,6 +128,19 @@ MCPToolMethodMutation >> classReferenceNameFor: className classSide: classSide [ ifFalse: [ className ] ] +{ #category : 'private - errors' } +MCPToolMethodMutation >> commandErrorForCompileFailure: anError methodSource: methodSource requestedContext: requestedContext summary: summary [ + + | commandError | + commandError := self + normalizedCommandErrorForActionFailure: anError + action: 'compile' + requestedContext: requestedContext + summary: summary. + self addCompileSourceContextFor: methodSource to: commandError details. + ^ commandError +] + { #category : 'private' } MCPToolMethodMutation >> critiqueDataFor: aCritique [