001 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
002 // for details. All rights reserved. Use of this source code is governed by a
003 // BSD-style license that can be found in the LICENSE file.
004
005 package com.google.dart.compiler.backend.js;
006
007 import com.google.dart.compiler.backend.js.ast.*;
008 import org.jetbrains.annotations.NotNull;
009
010 /**
011 * Determines if a statement at the end of a block requires a semicolon.
012 * <p/>
013 * For example, the following statements require semicolons:<br>
014 * <ul>
015 * <li>if (cond);</li>
016 * <li>while (cond);</li>
017 * </ul>
018 * <p/>
019 * The following do not require semicolons:<br>
020 * <ul>
021 * <li>return 1</li>
022 * <li>do {} while(true)</li>
023 * </ul>
024 */
025 public class JsRequiresSemiVisitor extends JsVisitor {
026 private boolean needsSemicolon;
027
028 private JsRequiresSemiVisitor() {
029 }
030
031 public static boolean exec(JsStatement lastStatement) {
032 JsRequiresSemiVisitor visitor = new JsRequiresSemiVisitor();
033 visitor.accept(lastStatement);
034 return visitor.needsSemicolon;
035 }
036
037 @Override
038 public void visitFor(@NotNull JsFor x) {
039 if (x.getBody() instanceof JsEmpty) {
040 needsSemicolon = true;
041 }
042 }
043
044 @Override
045 public void visitForIn(@NotNull JsForIn x) {
046 if (x.getBody() instanceof JsEmpty) {
047 needsSemicolon = true;
048 }
049 }
050
051 @Override
052 public void visitIf(@NotNull JsIf x) {
053 JsStatement thenStmt = x.getThenStatement();
054 JsStatement elseStmt = x.getElseStatement();
055 JsStatement toCheck = thenStmt;
056 if (elseStmt != null) {
057 toCheck = elseStmt;
058 }
059 if (toCheck instanceof JsEmpty) {
060 needsSemicolon = true;
061 }
062 else {
063 // Must recurse to determine last statement (possible if-else chain).
064 accept(toCheck);
065 }
066 }
067
068 @Override
069 public void visitLabel(@NotNull JsLabel x) {
070 if (x.getStatement() instanceof JsEmpty) {
071 needsSemicolon = true;
072 }
073 }
074
075 @Override
076 public void visitWhile(@NotNull JsWhile x) {
077 if (x.getBody() instanceof JsEmpty) {
078 needsSemicolon = true;
079 }
080 }
081 }