|
23 | 23 |
|
24 | 24 | import java.util.List; |
25 | 25 | import java.util.Locale; |
| 26 | +import java.util.NoSuchElementException; |
26 | 27 | import java.util.Optional; |
| 28 | +import java.util.function.BiFunction; |
27 | 29 | import java.util.function.Predicate; |
28 | 30 | import java.util.function.Supplier; |
29 | 31 |
|
30 | | -import com.google.common.base.CharMatcher; |
31 | 32 | import com.google.common.base.Splitter; |
32 | 33 | import com.google.common.base.Strings; |
33 | 34 | import com.google.common.collect.ImmutableList; |
@@ -242,24 +243,37 @@ default String resolve(final String text, final Config source) { |
242 | 243 | default String resolve(final String text, final Config source, |
243 | 244 | final String startDelimiter, final String endDelimiter) { |
244 | 245 | requireNonNull(text, "Text is required."); |
245 | | - requireNonNull(source, "A config source is required."); |
| 246 | + requireNonNull(source, "Config source is required."); |
246 | 247 | checkArgument(!Strings.isNullOrEmpty(startDelimiter), "Start delimiter is required."); |
247 | 248 | checkArgument(!Strings.isNullOrEmpty(endDelimiter), "End delimiter is required."); |
248 | 249 | if (text.length() == 0) { |
249 | 250 | return ""; |
250 | 251 | } |
| 252 | + |
| 253 | + BiFunction<Integer, BiFunction<Integer, Integer, RuntimeException>, RuntimeException> err = ( |
| 254 | + start, ex) -> { |
| 255 | + String snapshot = text.substring(0, start); |
| 256 | + int line = Splitter.on('\n').splitToList(snapshot).size(); |
| 257 | + int column = start - snapshot.lastIndexOf('\n'); |
| 258 | + return ex.apply(line, column); |
| 259 | + }; |
| 260 | + |
251 | 261 | StringBuilder buffer = new StringBuilder(); |
252 | 262 | int offset = 0; |
253 | 263 | int start = text.indexOf(startDelimiter); |
254 | 264 | while (start >= 0) { |
255 | 265 | int end = text.indexOf(endDelimiter, start + startDelimiter.length()); |
256 | 266 | if (end == -1) { |
257 | | - throw new IllegalArgumentException("Unclosed placeholder: " |
258 | | - + Splitter.on(CharMatcher.WHITESPACE) |
259 | | - .split(text.subSequence(start, text.length())).iterator().next()); |
| 267 | + throw err.apply(start, (line, column) -> new IllegalArgumentException( |
| 268 | + "found '" + startDelimiter + "' expecting '" + endDelimiter + "' at " + line + ":" |
| 269 | + + column)); |
260 | 270 | } |
261 | 271 | buffer.append(text.substring(offset, start)); |
262 | 272 | String key = text.substring(start + startDelimiter.length(), end); |
| 273 | + if (!source.hasPath(key)) { |
| 274 | + throw err.apply(start, (line, column) -> new NoSuchElementException( |
| 275 | + "No configuration setting found for key '" + key + "' at " + line + ":" + column)); |
| 276 | + } |
263 | 277 | buffer.append(source.getAnyRef(key)); |
264 | 278 | offset = end + endDelimiter.length(); |
265 | 279 | start = text.indexOf(startDelimiter, offset); |
|
0 commit comments