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 com.intellij.util.Function;
021    import com.intellij.util.containers.ContainerUtil;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
024    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
025    import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
026    import org.jetbrains.jet.lang.descriptors.Modality;
027    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
028    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
029    import org.jetbrains.jet.lang.psi.JetClass;
030    import org.jetbrains.jet.lang.psi.JetDeclaration;
031    import org.jetbrains.jet.lang.psi.JetFile;
032    import org.jetbrains.jet.lang.resolve.BindingContext;
033    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
034    import org.jetbrains.jet.lang.types.JetType;
035    import org.jetbrains.k2js.translate.utils.BindingUtils;
036    
037    import java.util.Collection;
038    import java.util.List;
039    
040    /**
041     * Helps find functions which are annotated with a @Test annotation from junit
042     */
043    public class JetTestFunctionDetector {
044        private JetTestFunctionDetector() {
045        }
046    
047        private static boolean isTest(@NotNull FunctionDescriptor functionDescriptor) {
048            Annotations annotations = functionDescriptor.getAnnotations();
049            for (AnnotationDescriptor annotation : annotations) {
050                // TODO ideally we should find the fully qualified name here...
051                JetType type = annotation.getType();
052                String name = type.toString();
053                if (name.equals("Test")) {
054                    return true;
055                }
056            }
057    
058            /*
059            if (function.getName().startsWith("test")) {
060                List<JetParameter> parameters = function.getValueParameters();
061                return parameters.size() == 0;
062            }
063            */
064            return false;
065        }
066    
067        @NotNull
068        public static List<FunctionDescriptor> getTestFunctionDescriptors(
069                @NotNull BindingContext bindingContext,
070                @NotNull Collection<JetFile> files
071        ) {
072            List<FunctionDescriptor> answer = Lists.newArrayList();
073            for (JetFile file : files) {
074                answer.addAll(getTestFunctions(bindingContext, file.getDeclarations()));
075            }
076            return answer;
077        }
078    
079        @NotNull
080        private static List<FunctionDescriptor> getTestFunctions(
081                @NotNull BindingContext bindingContext,
082                @NotNull List<JetDeclaration> declarations
083        ) {
084            List<FunctionDescriptor> answer = Lists.newArrayList();
085            for (JetDeclaration declaration : declarations) {
086                JetScope scope = null;
087    
088                if (declaration instanceof JetClass) {
089                    JetClass klass = (JetClass) declaration;
090                    ClassDescriptor classDescriptor = BindingUtils.getClassDescriptor(bindingContext, klass);
091    
092                    if (classDescriptor.getModality() != Modality.ABSTRACT) {
093                        scope = classDescriptor.getDefaultType().getMemberScope();
094                    }
095                }
096    
097                if (scope != null) {
098                    Collection<DeclarationDescriptor> allDescriptors = scope.getAllDescriptors();
099                    List<FunctionDescriptor> testFunctions = ContainerUtil.mapNotNull(
100                            allDescriptors,
101                            new Function<DeclarationDescriptor, FunctionDescriptor>() {
102                                @Override
103                                public FunctionDescriptor fun(DeclarationDescriptor descriptor) {
104                                    if (descriptor instanceof FunctionDescriptor) {
105                                        FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
106                                        if (isTest(functionDescriptor)) return functionDescriptor;
107                                    }
108    
109                                    return null;
110                                }
111                            });
112    
113                    answer.addAll(testFunctions);
114                }
115            }
116            return answer;
117        }
118    }