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