Skip to content

Commit 2ae1d24

Browse files
Copilotlaeubi
andauthored
Create dedicated Messages API (#103)
* Initial plan * Implement Messages API with builder pattern Co-authored-by: laeubi <[email protected]> * Fix log message formatting and clarify INFO mapping Co-authored-by: laeubi <[email protected]> * Address review feedback: shorter method names, package-private constructor, copyright removal, create(String message) Co-authored-by: laeubi <[email protected]> * Add @deprecated annotations and move formatLogMessage to Message.toString() Co-authored-by: laeubi <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: laeubi <[email protected]>
1 parent e1aba62 commit 2ae1d24

File tree

7 files changed

+511
-0
lines changed

7 files changed

+511
-0
lines changed

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,45 @@ The project was relocated from <https://github.com/sonatype/sisu-build-api>. Als
3232

3333
## Provided APIs
3434

35+
### Messages API
36+
37+
The Messages API provides a modern, flexible way to create and manage build messages/markers that inform users in an IDE about issues in their files. It uses a builder pattern for constructing messages in a more convenient and extensible way compared to the legacy BuildContext message methods.
38+
39+
**Key Features:**
40+
- Builder pattern for flexible message construction
41+
- Clear separation of concerns from resource operations
42+
- Support for error, warning, and info messages
43+
- File path-based message management
44+
- Optional line and column information
45+
- Optional exception cause association
46+
47+
**Example Usage:**
48+
49+
```java
50+
@Inject
51+
private Messages messages;
52+
53+
public void execute() {
54+
// Create an error message
55+
messages.error(Paths.get("/path/to/file.java"))
56+
.line(42)
57+
.column(10)
58+
.cause(exception)
59+
.create("Syntax error");
60+
61+
// Create a warning message
62+
messages.warning(Paths.get("/path/to/file.java"))
63+
.line(15)
64+
.create("Deprecated method used");
65+
66+
// Clear messages for a specific file
67+
messages.clear(Paths.get("/path/to/file.java"));
68+
69+
// Clear all messages
70+
messages.clearAll();
71+
}
72+
```
73+
3574
### Progress
3675

3776
The API allows a mojo to report progress in a way that is suitable to be shown as a progressbar as well as check if the user wants the mojo to gracefully abort its current operation.

src/main/java/org/codehaus/plexus/build/BuildContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ public interface BuildContext {
209209
* @param cause A Throwable object associated with the message. Can be null.
210210
* @since 0.0.7
211211
* @param message a {@link java.lang.String} object.
212+
* @deprecated Use {@link org.codehaus.plexus.build.messages.Messages} API instead
212213
*/
214+
@Deprecated
213215
void addMessage(File file, int line, int column, String message, int severity, Throwable cause);
214216

215217
/**
@@ -218,7 +220,9 @@ public interface BuildContext {
218220
*
219221
* @since 0.0.7
220222
* @param file a {@link java.io.File} object.
223+
* @deprecated Use {@link org.codehaus.plexus.build.messages.Messages#clear(java.nio.file.Path)} instead
221224
*/
225+
@Deprecated
222226
void removeMessages(File file);
223227

224228
/**
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
This program is licensed to you under the Apache License Version 2.0,
3+
and you may not use this file except in compliance with the Apache License Version 2.0.
4+
You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
5+
6+
Unless required by applicable law or agreed to in writing,
7+
software distributed under the Apache License Version 2.0 is distributed on an
8+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
10+
*/
11+
package org.codehaus.plexus.build.messages;
12+
13+
import javax.inject.Inject;
14+
import javax.inject.Named;
15+
import javax.inject.Singleton;
16+
17+
import java.nio.file.Path;
18+
19+
import org.codehaus.plexus.build.BuildContext;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
22+
23+
/**
24+
* Default implementation of the Messages interface.
25+
* <p>
26+
* This implementation delegates to the BuildContext for compatibility with existing
27+
* message handling infrastructure. It logs messages and calls the legacy BuildContext
28+
* message API.
29+
* </p>
30+
*/
31+
@Named("default")
32+
@Singleton
33+
public class DefaultMessages implements Messages {
34+
35+
private static final Logger logger = LoggerFactory.getLogger(DefaultMessages.class);
36+
37+
private final BuildContext buildContext;
38+
39+
/**
40+
* Creates a new DefaultMessages instance.
41+
*
42+
* @param buildContext the BuildContext to which messages will be delegated
43+
*/
44+
@Inject
45+
public DefaultMessages(BuildContext buildContext) {
46+
this.buildContext = buildContext;
47+
}
48+
49+
@Override
50+
public void clearAll() {
51+
// This is a no-op in the default implementation
52+
// Custom implementations may provide actual clearing functionality
53+
}
54+
55+
@Override
56+
public void clear(Path path) {
57+
if (path != null) {
58+
buildContext.removeMessages(path.toFile());
59+
}
60+
}
61+
62+
@Override
63+
public MessageBuilder error(Path path) {
64+
return build(MessageType.ERROR, path);
65+
}
66+
67+
@Override
68+
public MessageBuilder warning(Path path) {
69+
return build(MessageType.WARNING, path);
70+
}
71+
72+
@Override
73+
public MessageBuilder info(Path path) {
74+
return build(MessageType.INFO, path);
75+
}
76+
77+
@Override
78+
public MessageBuilder build(MessageType type, Path path) {
79+
return new MessageBuilder(type, path, this::handleMessage);
80+
}
81+
82+
/**
83+
* Handles a message by logging it and delegating to the BuildContext.
84+
*
85+
* @param message the message to handle
86+
*/
87+
private void handleMessage(Message message) {
88+
// Log the message
89+
String logMessage = message.toString();
90+
91+
switch (message.getType()) {
92+
case ERROR:
93+
logger.error(logMessage, message.getCause());
94+
break;
95+
case WARNING:
96+
logger.warn(logMessage, message.getCause());
97+
break;
98+
case INFO:
99+
logger.info(logMessage, message.getCause());
100+
break;
101+
}
102+
103+
// Delegate to BuildContext for compatibility
104+
if (message.getPath() != null) {
105+
int severity = mapTypeToSeverity(message.getType());
106+
buildContext.addMessage(
107+
message.getPath().toFile(),
108+
message.getLine(),
109+
message.getColumn(),
110+
message.getMessage(),
111+
severity,
112+
message.getCause());
113+
}
114+
}
115+
116+
/**
117+
* Maps a MessageType to a BuildContext severity level.
118+
*
119+
* @param type the message type
120+
* @return the corresponding BuildContext severity
121+
*/
122+
private int mapTypeToSeverity(MessageType type) {
123+
switch (type) {
124+
case ERROR:
125+
return BuildContext.SEVERITY_ERROR;
126+
case WARNING:
127+
return BuildContext.SEVERITY_WARNING;
128+
case INFO:
129+
default:
130+
// BuildContext supports 0 as an info severity level (undocumented)
131+
return 0;
132+
}
133+
}
134+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
This program is licensed to you under the Apache License Version 2.0,
3+
and you may not use this file except in compliance with the Apache License Version 2.0.
4+
You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
5+
6+
Unless required by applicable law or agreed to in writing,
7+
software distributed under the Apache License Version 2.0 is distributed on an
8+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
10+
*/
11+
package org.codehaus.plexus.build.messages;
12+
13+
import java.nio.file.Path;
14+
15+
/**
16+
* Represents a message with all its parameters.
17+
* This class holds the collected parameters for a message that can be created through the MessageBuilder.
18+
*/
19+
public class Message {
20+
private final MessageType type;
21+
private final Path path;
22+
private final int line;
23+
private final int column;
24+
private final String message;
25+
private final Throwable cause;
26+
27+
/**
28+
* Creates a new message with the specified parameters.
29+
*
30+
* @param type the message type
31+
* @param path the file path associated with this message
32+
* @param line the line number (1-based, 0 for unknown)
33+
* @param column the column number (1-based, 0 for unknown)
34+
* @param message the message text
35+
* @param cause the exception cause, can be null
36+
*/
37+
Message(MessageType type, Path path, int line, int column, String message, Throwable cause) {
38+
this.type = type;
39+
this.path = path;
40+
this.line = line;
41+
this.column = column;
42+
this.message = message;
43+
this.cause = cause;
44+
}
45+
46+
/**
47+
* @return the message type
48+
*/
49+
public MessageType getType() {
50+
return type;
51+
}
52+
53+
/**
54+
* @return the file path
55+
*/
56+
public Path getPath() {
57+
return path;
58+
}
59+
60+
/**
61+
* @return the line number (1-based, 0 for unknown)
62+
*/
63+
public int getLine() {
64+
return line;
65+
}
66+
67+
/**
68+
* @return the column number (1-based, 0 for unknown)
69+
*/
70+
public int getColumn() {
71+
return column;
72+
}
73+
74+
/**
75+
* @return the message text
76+
*/
77+
public String getMessage() {
78+
return message;
79+
}
80+
81+
/**
82+
* @return the exception cause, or null if none
83+
*/
84+
public Throwable getCause() {
85+
return cause;
86+
}
87+
88+
/**
89+
* Returns a string representation of this message.
90+
* The format is: path [line:column]: message
91+
*
92+
* @return the formatted message string
93+
*/
94+
@Override
95+
public String toString() {
96+
StringBuilder sb = new StringBuilder();
97+
98+
if (path != null) {
99+
sb.append(path.toAbsolutePath());
100+
}
101+
102+
if (line > 0 && column > 0) {
103+
sb.append(" [");
104+
sb.append(line);
105+
sb.append(':').append(column);
106+
sb.append("]");
107+
} else if (line > 0) {
108+
sb.append(" [");
109+
sb.append(line);
110+
sb.append("]");
111+
} else if (column > 0) {
112+
sb.append(" [:");
113+
sb.append(column);
114+
sb.append("]");
115+
}
116+
117+
if (message != null) {
118+
if (sb.length() > 0) {
119+
sb.append(": ");
120+
}
121+
sb.append(message);
122+
}
123+
124+
return sb.toString();
125+
}
126+
}

0 commit comments

Comments
 (0)