001    /*
002     * Copyright 2010-2014 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.jet.lang.psi.stubs.impl;
018    
019    import com.intellij.psi.stubs.StubElement;
020    import com.intellij.util.ArrayUtil;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.jet.lang.psi.JetModifierList;
023    import org.jetbrains.jet.lang.psi.stubs.PsiJetModifierListStub;
024    import org.jetbrains.jet.lang.psi.stubs.elements.JetModifierListElementType;
025    import org.jetbrains.jet.lexer.JetModifierKeywordToken;
026    
027    import static org.jetbrains.jet.lexer.JetTokens.MODIFIER_KEYWORDS_ARRAY;
028    
029    public class PsiJetModifierListStubImpl extends JetStubBaseImpl<JetModifierList> implements PsiJetModifierListStub {
030    
031        static {
032            assert MODIFIER_KEYWORDS_ARRAY.length <= 32 : "Current implementation depends on the ability to represent modifier list as bit mask";
033        }
034    
035        public static int computeMaskFromPsi(@NotNull JetModifierList modifierList) {
036            int mask = 0;
037            JetModifierKeywordToken[] orderedKeywords = MODIFIER_KEYWORDS_ARRAY;
038            for (int i = 0; i < orderedKeywords.length; i++) {
039                JetModifierKeywordToken modifierKeywordToken = orderedKeywords[i];
040                if (modifierList.hasModifier(modifierKeywordToken)) {
041                    mask |= 1 << i;
042                }
043            }
044            return mask;
045        }
046    
047        private final int mask;
048    
049        public PsiJetModifierListStubImpl(StubElement parent, int mask, @NotNull JetModifierListElementType<?> elementType) {
050            super(parent, elementType);
051            this.mask = mask;
052        }
053    
054        @Override
055        public boolean hasModifier(@NotNull JetModifierKeywordToken modifierToken) {
056            int index = ArrayUtil.indexOf(MODIFIER_KEYWORDS_ARRAY, modifierToken);
057            assert index >= 0 : "All JetModifierKeywordTokens should present in MODIFIER_KEYWORDS_ARRAY";
058            return (mask & (1 << index)) != 0;
059        }
060    
061        public int getMask() {
062            return mask;
063        }
064    
065        @Override
066        public String toString() {
067            StringBuilder sb = new StringBuilder();
068            sb.append(super.toString());
069            sb.append("[");
070            boolean first = true;
071            for (JetModifierKeywordToken modifierKeyword : MODIFIER_KEYWORDS_ARRAY) {
072                if (hasModifier(modifierKeyword)) {
073                    if (!first) {
074                        sb.append(" ");
075                    }
076                    sb.append(modifierKeyword.getValue());
077                    first = false;
078                }
079            }
080            sb.append("]");
081            return sb.toString();
082        }
083    }