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.general;
018    
019    import com.google.common.collect.Lists;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
022    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
023    import org.jetbrains.jet.lang.psi.JetClass;
024    import org.jetbrains.jet.lang.psi.JetDeclaration;
025    import org.jetbrains.jet.lang.psi.JetFile;
026    import org.jetbrains.jet.lang.psi.JetNamedFunction;
027    import org.jetbrains.jet.lang.resolve.BindingContext;
028    import org.jetbrains.jet.lang.types.JetType;
029    
030    import java.util.Collection;
031    import java.util.List;
032    
033    import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
034    import static org.jetbrains.k2js.translate.utils.BindingUtils.getNullableDescriptorForFunction;
035    
036    /**
037     * Helps find functions which are annotated with a @Test annotation from junit
038     */
039    public class JetTestFunctionDetector {
040        private JetTestFunctionDetector() {
041        }
042    
043        private static boolean isTest(@NotNull BindingContext bindingContext, @NotNull JetNamedFunction function) {
044            FunctionDescriptor functionDescriptor = getNullableDescriptorForFunction(bindingContext, function);
045            if (functionDescriptor == null) {
046                return false;
047            }
048            List<AnnotationDescriptor> annotations = functionDescriptor.getAnnotations();
049            if (annotations != null) {
050                for (AnnotationDescriptor annotation : annotations) {
051                    // TODO ideally we should find the fully qualified name here...
052                    JetType type = annotation.getType();
053                    String name = type.toString();
054                    if (name.equals("Test")) {
055                        return true;
056                    }
057                }
058            }
059    
060            /*
061            if (function.getName().startsWith("test")) {
062                List<JetParameter> parameters = function.getValueParameters();
063                return parameters.size() == 0;
064            }
065            */
066            return false;
067        }
068    
069        @NotNull
070        private static List<JetNamedFunction> findTestFunctions(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files) {
071            List<JetNamedFunction> answer = Lists.newArrayList();
072            for (JetFile file : files) {
073                answer.addAll(getTestFunctions(bindingContext, file.getDeclarations()));
074            }
075            return answer;
076        }
077    
078        @NotNull
079        public static List<FunctionDescriptor> getTestFunctionDescriptors(@NotNull BindingContext bindingContext, @NotNull Collection<JetFile> files) {
080            List<FunctionDescriptor> answer = Lists.newArrayList();
081            for (JetNamedFunction function : findTestFunctions(bindingContext, files)) {
082                answer.add(getFunctionDescriptor(bindingContext, function));
083            }
084            return answer;
085        }
086    
087        @NotNull
088        private static List<JetNamedFunction> getTestFunctions(@NotNull BindingContext bindingContext,
089                @NotNull List<JetDeclaration> declarations) {
090            List<JetNamedFunction> answer = Lists.newArrayList();
091            for (JetDeclaration declaration : declarations) {
092                if (declaration instanceof JetClass) {
093                    JetClass klass = (JetClass) declaration;
094                    answer.addAll(getTestFunctions(bindingContext, klass.getDeclarations()));
095                }
096                else if (declaration instanceof JetNamedFunction) {
097                    JetNamedFunction candidateFunction = (JetNamedFunction) declaration;
098                    if (isTest(bindingContext, candidateFunction)) {
099                        answer.add(candidateFunction);
100                    }
101                }
102            }
103            return answer;
104        }
105    }