aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/packages/AnalysisIssues.java
blob: e86ae40d606574e2a3e6df0b198da555ed503ca1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.packages;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Checked exception for analysis-time errors, which can store the errors for later reporting.
 *
 * <p>It's more robust for a method to throw this exception than expecting a
 * {@link RuleErrorConsumer} object (which may be null).
 */
public final class AnalysisIssues extends Exception {

  /**
   * An error entry.
   *
   * <p>{@link AnalysisIssues} can accumulate multiple of these, and report all of them at once.
   */
  public static final class Entry {
    private final String attribute;
    private final String messageTemplate;
    private final Object[] arguments;

    private Entry(@Nullable String attribute, String messageTemplate, Object... arguments) {
      this.attribute = attribute;
      this.messageTemplate = messageTemplate;
      this.arguments = arguments;
    }

    private void reportTo(RuleErrorConsumer errors) {
      String msg = String.format(messageTemplate, arguments);
      if (attribute == null) {
        errors.ruleError(msg);
      } else {
        errors.attributeError(attribute, msg);
      }
    }

    private void reportTo(StringBuilder sb) {
      String msg = String.format(messageTemplate, arguments);
      if (attribute == null) {
        sb.append("ERROR: ").append(msg);
      } else {
        sb.append("ERROR: in attribute \"").append(attribute).append("\": ").append(msg);
      }
    }

    @Override
    public String toString() {
      if (attribute == null) {
        return String.format("ERROR: " + messageTemplate, arguments);
      } else {
        List<Object> args = new ArrayList<>();
        args.add(attribute);
        Collections.addAll(args, arguments);
        return String.format("ERROR in '%s': " + messageTemplate, args.toArray());
      }
    }
  }

  private final ImmutableList<Entry> entries;

  public AnalysisIssues(Entry entry) {
    this.entries = ImmutableList.of(Preconditions.checkNotNull(entry));
  }

  public AnalysisIssues(Collection<Entry> entries) {
    this.entries = ImmutableList.copyOf(Preconditions.checkNotNull(entries));
  }

  /**
   * Creates a attribute error entry that will be added to a {@link AnalysisIssues} later.
   */
  public static Entry attributeError(String attribute, String messageTemplate,
      Object... arguments) {
    return new Entry(attribute, messageTemplate, arguments);
  }

  public static Entry ruleError(String messageTemplate, Object... arguments) {
    return new Entry(null, messageTemplate, arguments);
  }

  /**
   * Report all accumulated errors and warnings to the given consumer object.
   */
  public void reportTo(RuleErrorConsumer errors) {
    Preconditions.checkNotNull(errors);
    for (Entry e : entries) {
      e.reportTo(errors);
    }
  }

  @Nullable
  private String asString() {
    if (entries == null) {
      return null;
    }

    StringBuilder sb = new StringBuilder();
    for (Entry e : entries) {
      e.reportTo(sb);
    }
    return sb.toString();
  }

  @Override
  public String getMessage() {
    return asString();
  }

  @Override
  public String toString() {
    String s = asString();
    return s == null ? "" : s;
  }
}