001    /*
002     * Copyright 2010-2012 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.js.compiler;
018    
019    import com.google.dart.compiler.backend.js.JsToStringGenerationVisitor;
020    import com.google.dart.compiler.backend.js.ast.*;
021    import com.google.dart.compiler.util.TextOutput;
022    import org.jetbrains.annotations.Nullable;
023    
024    public class JsSourceGenerationVisitor extends JsToStringGenerationVisitor implements TextOutput.OutListener {
025        @Nullable
026        private final SourceMapBuilder sourceMapBuilder;
027    
028        private Object pendingSourceInfo;
029    
030        public JsSourceGenerationVisitor(TextOutput out, @Nullable SourceMapBuilder sourceMapBuilder) {
031            super(out);
032            this.sourceMapBuilder = sourceMapBuilder;
033            out.setOutListener(this);
034        }
035    
036        @Override
037        public boolean visit(JsProgram program, JsContext ctx) {
038            return true;
039        }
040    
041        @Override
042        public boolean visit(JsProgramFragment x, JsContext ctx) {
043            // Descend naturally.
044            return true;
045        }
046    
047        @Override
048        public boolean visit(JsBlock x, JsContext ctx) {
049            printJsBlock(x, false, true);
050            return false;
051        }
052    
053        @Override
054        public void newLined() {
055            if (sourceMapBuilder != null) {
056                sourceMapBuilder.newLine();
057            }
058        }
059    
060        @Override
061        public void indentedAfterNewLine() {
062            if (pendingSourceInfo != null) {
063                assert sourceMapBuilder != null;
064                sourceMapBuilder.processSourceInfo(pendingSourceInfo);
065                pendingSourceInfo = null;
066            }
067        }
068    
069        @Override
070        protected void doTraverse(JsVisitable node, JsContext context) {
071            if (sourceMapBuilder != null) {
072                Object sourceInfo = node.getSourceInfo();
073                if (sourceInfo != null) {
074                    assert pendingSourceInfo == null;
075                    if (p.isJustNewlined()) {
076                        pendingSourceInfo = sourceInfo;
077                    }
078                    else {
079                        sourceMapBuilder.processSourceInfo(sourceInfo);
080                    }
081                }
082            }
083            super.doTraverse(node, context);
084        }
085    
086        @Override
087        public void endVisit(JsProgram x, JsContext context) {
088            super.endVisit(x, context);
089            if (sourceMapBuilder != null) {
090                sourceMapBuilder.addLink();
091            }
092        }
093    }