001 /*
002 * Copyright 2010-2013 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.k2js.translate.utils.dangerous;
018
019 import com.google.common.collect.Maps;
020 import com.intellij.psi.PsiElement;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.jet.lang.psi.*;
023
024 import java.util.Map;
025
026 import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression;
027
028 //TODO: refactor
029 public final class FindPreviousVisitor extends JetTreeVisitor<DangerousData> {
030
031 @NotNull
032 private final Map<JetElement, Void> hasDangerous = Maps.newHashMap();
033
034 public FindPreviousVisitor(@NotNull DangerousData data) {
035 JetElement node = data.getDangerousNode();
036 PsiElement last = data.getRootNode().getParent();
037 while (node != last) {
038 hasDangerous.put(node, null);
039 PsiElement parent = node.getParent();
040 assert parent instanceof JetElement;
041 node = (JetElement)parent;
042 }
043 }
044
045 @Override
046 public Void visitJetElement(JetElement element, DangerousData data) {
047 if (data.getDangerousNode() == element) {
048 return null;
049 }
050 if (!hasDangerous(element)) {
051 addElement(element, data);
052 }
053 else {
054 acceptChildrenThatAreBeforeTheDangerousNode(element, data);
055 }
056 return null;
057 }
058
059 //TODO: return value not used, wtf?
060 private static boolean addElement(@NotNull JetElement element, @NotNull DangerousData data) {
061 if (element instanceof JetExpression) {
062 data.getNodesToBeGeneratedBefore().add((JetExpression)element);
063 return true;
064 }
065 return false;
066 }
067
068 private void acceptChildrenThatAreBeforeTheDangerousNode(@NotNull JetElement element, @NotNull DangerousData data) {
069 PsiElement current = element.getFirstChild();
070 while (current != null) {
071 if (current instanceof JetElement) {
072 ((JetElement)current).accept(this, data);
073 if (hasDangerous(element)) {
074 break;
075 }
076 }
077 current = current.getNextSibling();
078 }
079 }
080
081 @Override
082 public Void visitPrefixExpression(@NotNull JetPrefixExpression expression, @NotNull DangerousData data) {
083 if (data.getDangerousNode() == expression) {
084 return null;
085 }
086 if (!hasDangerous(expression)) {
087 addElement(expression, data);
088 return null;
089 }
090 else {
091 if (hasDangerous(getBaseExpression(expression))) {
092 return null;
093 }
094 else {
095 //TODO:
096 throw new IllegalStateException();
097 }
098 }
099 }
100
101 @Override
102 public Void visitCallExpression(@NotNull JetCallExpression expression, @NotNull DangerousData data) {
103 if (data.getDangerousNode() == expression) {
104 return null;
105 }
106 if (!hasDangerous(expression)) {
107 data.getNodesToBeGeneratedBefore().add(expression);
108 }
109 else {
110 acceptArgumentsThatAreBeforeDangerousNode(expression, data);
111 }
112 return null;
113 }
114
115 private void acceptArgumentsThatAreBeforeDangerousNode(@NotNull JetCallExpression expression, @NotNull DangerousData data) {
116 for (ValueArgument argument : expression.getValueArguments()) {
117 JetExpression argumentExpression = argument.getArgumentExpression();
118 assert argumentExpression != null;
119 argumentExpression.accept(this, data);
120 if (hasDangerous(argumentExpression)) {
121 break;
122 }
123 }
124 }
125
126 private boolean hasDangerous(@NotNull JetElement element) {
127 return hasDangerous.containsKey(element);
128 }
129 }