/*
 * Copyright 2016 Google Inc.
 *
 * 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.j2cl.ast.visitors;

import static com.google.common.base.Preconditions.checkState;

import com.google.common.base.Predicates;
import com.google.j2cl.ast.AbstractVisitor;
import com.google.j2cl.ast.CompilationUnit;
import com.google.j2cl.ast.Field;
import com.google.j2cl.ast.Member;
import com.google.j2cl.ast.Method;
import com.google.j2cl.ast.Type;

/** Verifies that the AST satisfies the normalization invariants. */
public class VerifyNormalizedUnits {

  public static void applyTo(CompilationUnit compilationUnit) {
    // All native methods should be empty.
    compilationUnit.accept(
        new AbstractVisitor() {
          @Override
          public void exitField(Field field) {
            checkState(!field.isNative());
          }

          @Override
          public void exitMethod(Method method) {
            checkState(!method.isNative() || method.getBody().isEmpty());
          }
        });

    for (Type type : compilationUnit.getTypes()) {
      // Native and JsFunction types should have been removed from the AST.
      checkState(!type.isNative());
      checkState(!type.isJsFunctionInterface());
      // JsEnum only contains the enum fields.
      if (type.isJsEnum()) {
        checkState(
            type.getMembers().stream().allMatch(Predicates.and(Member::isField, Member::isStatic)));
      }
    }
  }

  private VerifyNormalizedUnits() {}
}

@@ -691,50 +691,8 @@
 e;%0A%0A
-import com.google.common.base.Predicates;%0A
 impo
@@ -1088,51 +1088,8 @@
 ) %7B%0A
-    // All native methods should be empty.%0A
     
@@ -1140,24 +1140,280 @@
 Visitor() %7B%0A
+          @Override%0A          public void exitType(Type type) %7B%0A            // Native and JsFunction types should have been removed from the AST.%0A            checkState(!type.isNative());%0A            checkState(!type.isJsFunctionInterface());%0A          %7D%0A%0A
           @O
@@ -1589,24 +1589,75 @@
 d method) %7B%0A
+            // All native methods should be empty.%0A
             
@@ -1730,24 +1730,25 @@
       %7D%0A
+%0A
         
 %7D);%0A%0A   
@@ -1743,225 +1743,76 @@
     
-%7D);%0A%0A    for (Type type : compilationUnit.getTypes()) %7B%0A      // Native and JsFunction types should have been removed from the AST.%0A      checkState(!type.isNative());%0A      checkState(!type.isJsFunctionInterface());%0A
+  @Override%0A          public void exitMember(Member member) %7B%0A      
     
@@ -1864,16 +1864,34 @@
     
+ 
-if (t
+     if (getCurrentT
 ype
+()
 .isJ
@@ -1913,116 +1913,60 @@
     
-checkState(%0A            type.getMembers().stream().allMatch(Predicates.and(M
+      checkState(m
 ember
-::
+.
 isField
-, M
+() %7C%7C m
 ember
-::
+.
 isStatic
 )));
@@ -1961,17 +1961,17 @@
 isStatic
-)
+(
 ));%0A    
@@ -1976,15 +1976,39 @@
     
+    
-%7D%0A    %7D
+  %7D%0A          %7D%0A        %7D);
 %0A  %7D

Change VerifyNormalizeUnits to be more consistent and also provide context when the verification fails.