Package org.qi4j.ide.plugin.idea.mixins.inspections

Source Code of org.qi4j.ide.plugin.idea.mixins.inspections.MixinImplementsMixinType$RemoveInvalidMixinClassReferenceFix

/*  Copyright 2008 Edward Yakop.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.qi4j.ide.plugin.idea.mixins.inspections;

import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotationMemberValue;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import org.jetbrains.annotations.NotNull;
import org.qi4j.ide.plugin.idea.common.inspections.AbstractFix;
import org.qi4j.ide.plugin.idea.common.inspections.AbstractInspection;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message;
import static org.qi4j.ide.plugin.idea.concerns.common.Qi4jConcernUtil.isAConcern;
import static org.qi4j.ide.plugin.idea.mixins.common.Qi4jMixinUtil.*;
import static org.qi4j.ide.plugin.idea.sideEffects.common.Qi4jSideEffectUtil.isASideEffect;

/**
* @author edward.yakop@gmail.com
* @since 0.1
*/
public final class MixinImplementsMixinType extends AbstractInspection
{
    @NotNull
    protected final String resourceBundlePrefixId()
    {
        return "mixin.implements.mixin.type";
    }

    @NotNull
    public final String getShortName()
    {
        return "MixinImplementsMixinType";
    }

    @Override
    public final ProblemDescriptor[] checkClass( @NotNull PsiClass psiClass,
                                                 @NotNull InspectionManager manager,
                                                 boolean isOnTheFly )
    {
        // If psiClass is not an interface, ignore
        if( !psiClass.isInterface() )
        {
            return null;
        }

        // If @Mixins annotation is empty, ignore
        List<PsiAnnotationMemberValue> mixinAnnotationValues = getMixinsAnnotationValue( psiClass );
        if( mixinAnnotationValues.isEmpty() )
        {
            return null;
        }

        // Get all valid mixin type
        Set<PsiClass> validMixinsType = getAllValidMixinTypes( psiClass );
        if( validMixinsType.isEmpty() )
        {
            return null;
        }

        // For each mixin
        List<ProblemDescriptor> problems = new LinkedList<ProblemDescriptor>();
        for( PsiAnnotationMemberValue mixinAnnotationValue : mixinAnnotationValues )
        {
            PsiJavaCodeReferenceElement mixinClassReference = getMixinClassReference( mixinAnnotationValue );

            // If it's not a class reference, ignore
            if( mixinClassReference == null )
            {
                continue;
            }

            // If class reference can't be resolved, ignore
            PsiClass mixinClass = (PsiClass) mixinClassReference.resolve();
            if( mixinClass == null )
            {
                continue;
            }

            String mixinQualifiedName = mixinClass.getQualifiedName();

            boolean isMixinsDeclarationValid = false;
            String message = "";
            if( mixinClass.isInterface() )
            {
                // Mixin can't be an interface
                message = message( "mixin.implements.mixin.type.error.mixin.is.an.interface", mixinQualifiedName );
            }
            else if( isAConcern( mixinClass ) )
            {
                // Mixin can't be a concern
                message = message( "mixin.implements.mixin.type.error.mixin.is.a.concern", mixinQualifiedName );
            }
            else if( isASideEffect( mixinClass ) )
            {
                // Mixin can't be a side effect
                message = message( "mixin.implements.mixin.type.error.mixin.is.a.side.effect", mixinQualifiedName );
            }
            else
            {
                // If doesn't implement any mixin type, it's a problem
                if( !isImplementValidMixinType( mixinClass, validMixinsType ) )
                {
                    message = message(
                        "mixin.implements.mixin.type.error.does.not.implement.any.mixin.type",
                        mixinQualifiedName,
                        psiClass.getQualifiedName()
                    );
                }
                else
                {
                    isMixinsDeclarationValid = true;
                }
            }

            if( !isMixinsDeclarationValid )
            {
                ProblemDescriptor problemDescriptor = createProblemDescriptor(
                    manager, mixinAnnotationValue, mixinClassReference, message );
                problems.add( problemDescriptor );
            }
        }

        return problems.toArray( new ProblemDescriptor[problems.size()] );
    }

    private boolean isImplementValidMixinType( PsiClass mixinClass, Set<PsiClass> validMixinsType )
    {
        for( PsiClass validMixinTypeClass : validMixinsType )
        {
            if( mixinClass.isInheritor( validMixinTypeClass, true ) )
            {
                return true;
            }
        }

        return false;
    }

    private ProblemDescriptor createProblemDescriptor( @NotNull InspectionManager manager,
                                                       @NotNull PsiAnnotationMemberValue mixinAnnotationValue,
                                                       @NotNull PsiJavaCodeReferenceElement mixinClassReference,
                                                       @NotNull String message )
    {
        RemoveInvalidMixinClassReferenceFix fix = new RemoveInvalidMixinClassReferenceFix(
            mixinAnnotationValue, mixinClassReference
        );
        return manager.createProblemDescriptor( mixinAnnotationValue, message, fix, GENERIC_ERROR_OR_WARNING );
    }

    private static class RemoveInvalidMixinClassReferenceFix extends AbstractFix
    {
        private final PsiAnnotationMemberValue mixinClassAnnotationValue;

        public RemoveInvalidMixinClassReferenceFix( @NotNull PsiAnnotationMemberValue mixinClassAnnotationValue,
                                                    @NotNull PsiJavaCodeReferenceElement mixinClassReference )
        {
            super( message( "mixin.implements.mixin.type.fix.remove.class.reference", mixinClassReference.getQualifiedName() ) );
            this.mixinClassAnnotationValue = mixinClassAnnotationValue;
        }

        public final void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor )
        {
            mixinClassAnnotationValue.delete();
        }
    }
}
TOP

Related Classes of org.qi4j.ide.plugin.idea.mixins.inspections.MixinImplementsMixinType$RemoveInvalidMixinClassReferenceFix

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.