• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.google.api.generator.engine.ast;
16 
17 import com.google.auto.value.AutoValue;
18 import com.google.common.base.Preconditions;
19 import javax.annotation.Nullable;
20 
21 @AutoValue
22 public abstract class ThrowExpr implements Expr {
23   // TODO(miraleung): Refactor with StringObjectValue and possibly with NewObjectExpr.
24 
25   @Nullable
throwExpr()26   public abstract Expr throwExpr();
27 
28   @Override
type()29   public abstract TypeNode type();
30 
31   @Nullable
messageExpr()32   public abstract Expr messageExpr();
33 
34   @Nullable
causeExpr()35   public abstract Expr causeExpr();
36 
37   @Override
accept(AstNodeVisitor visitor)38   public void accept(AstNodeVisitor visitor) {
39     visitor.visit(this);
40   }
41 
builder()42   public static Builder builder() {
43     return new AutoValue_ThrowExpr.Builder();
44   }
45 
46   @AutoValue.Builder
47   public abstract static class Builder {
setThrowExpr(Expr throwExpr)48     public abstract Builder setThrowExpr(Expr throwExpr);
49 
50     // No-op if setThrowExpr is called.
setType(TypeNode type)51     public abstract Builder setType(TypeNode type);
52 
setMessageExpr(String message)53     public Builder setMessageExpr(String message) {
54       return setMessageExpr(ValueExpr.withValue(StringObjectValue.withValue(message)));
55     }
56 
setMessageExpr(Expr expr)57     public abstract Builder setMessageExpr(Expr expr);
58 
setCauseExpr(Expr expr)59     public abstract Builder setCauseExpr(Expr expr);
60 
61     // Private.
throwExpr()62     abstract Expr throwExpr();
63 
type()64     abstract TypeNode type();
65 
messageExpr()66     abstract Expr messageExpr();
67 
causeExpr()68     abstract Expr causeExpr();
69 
autoBuild()70     abstract ThrowExpr autoBuild();
71 
build()72     public ThrowExpr build() {
73       if (throwExpr() != null) {
74         setType(throwExpr().type());
75         Preconditions.checkState(
76             messageExpr() == null && causeExpr() == null,
77             "Only one of throwExpr or [messageExpr or causeExpr, inclusive] can be present.");
78 
79         if (throwExpr() instanceof VariableExpr) {
80           Preconditions.checkState(
81               !((VariableExpr) throwExpr()).isDecl(), "Cannot throw a variable declaration");
82         }
83 
84         Preconditions.checkState(
85             TypeNode.isExceptionType(throwExpr().type()),
86             String.format("Only exception types can be thrown, found %s", throwExpr().type()));
87 
88         return autoBuild();
89       }
90 
91       Preconditions.checkState(
92           TypeNode.isExceptionType(type()),
93           String.format("Type %s must be an exception type", type()));
94 
95       if (messageExpr() != null) {
96         Preconditions.checkState(
97             messageExpr().type().equals(TypeNode.STRING),
98             String.format("Message expression type must be a string for exception %s", type()));
99       }
100 
101       if (causeExpr() != null) {
102         Preconditions.checkState(
103             TypeNode.THROWABLE.reference().isSupertypeOrEquals(causeExpr().type().reference()),
104             String.format(
105                 "Cause expression type must be a subclass of Throwable, but found %s",
106                 causeExpr().type()));
107       }
108 
109       return autoBuild();
110     }
111   }
112 }
113