001    /*
002     * Copyright 2010-2015 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.kotlin.types.expressions;
018    
019    import com.google.common.collect.ImmutableBiMap;
020    import com.google.common.collect.ImmutableMap;
021    import com.google.common.collect.ImmutableSet;
022    import org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.kotlin.lexer.KtSingleValueToken;
025    import org.jetbrains.kotlin.lexer.KtToken;
026    import org.jetbrains.kotlin.lexer.KtTokens;
027    import org.jetbrains.kotlin.name.Name;
028    
029    import static org.jetbrains.kotlin.util.OperatorNameConventions.*;
030    
031    public class OperatorConventions {
032    
033        private OperatorConventions() {}
034    
035        // Names for primitive type conversion properties
036        public static final Name DOUBLE = Name.identifier("toDouble");
037        public static final Name FLOAT = Name.identifier("toFloat");
038        public static final Name LONG = Name.identifier("toLong");
039        public static final Name INT = Name.identifier("toInt");
040        public static final Name CHAR = Name.identifier("toChar");
041        public static final Name SHORT = Name.identifier("toShort");
042        public static final Name BYTE = Name.identifier("toByte");
043    
044    
045        public static final ImmutableSet<Name> NUMBER_CONVERSIONS = ImmutableSet.of(
046                DOUBLE, FLOAT, LONG, INT, SHORT, BYTE, CHAR
047        );
048    
049        // If you add new unary, binary or assignment operators, add it to OperatorConventionNames as well
050    
051        public static final ImmutableBiMap<KtSingleValueToken, Name> UNARY_OPERATION_NAMES = ImmutableBiMap.<KtSingleValueToken, Name>builder()
052                .put(KtTokens.PLUSPLUS, INC)
053                .put(KtTokens.MINUSMINUS, DEC)
054                .put(KtTokens.PLUS, UNARY_PLUS)
055                .put(KtTokens.MINUS, UNARY_MINUS)
056                .put(KtTokens.EXCL, NOT)
057                .build();
058    
059        public static final ImmutableMap<Name, KtSingleValueToken> UNARY_OPERATION_NAMES_WITH_DEPRECATED_INVERTED = ImmutableMap.<Name, KtSingleValueToken>builder()
060                .put(INC, KtTokens.PLUSPLUS)
061                .put(DEC, KtTokens.MINUSMINUS)
062                .put(UNARY_PLUS, KtTokens.PLUS)
063                .put(PLUS, KtTokens.PLUS)
064                .put(UNARY_MINUS, KtTokens.MINUS)
065                .put(MINUS, KtTokens.MINUS)
066                .put(NOT, KtTokens.EXCL)
067                .build();
068    
069        public static final ImmutableBiMap<KtSingleValueToken, Name> BINARY_OPERATION_NAMES = ImmutableBiMap.<KtSingleValueToken, Name>builder()
070                .put(KtTokens.MUL, TIMES)
071                .put(KtTokens.PLUS, PLUS)
072                .put(KtTokens.MINUS, MINUS)
073                .put(KtTokens.DIV, DIV)
074                .put(KtTokens.PERC, MOD)
075                .put(KtTokens.RANGE, RANGE_TO)
076                .build();
077    
078        public static final ImmutableSet<KtSingleValueToken> NOT_OVERLOADABLE =
079                ImmutableSet.of(KtTokens.ANDAND, KtTokens.OROR, KtTokens.ELVIS, KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ);
080        
081        public static final ImmutableSet<KtSingleValueToken> INCREMENT_OPERATIONS =
082                ImmutableSet.of(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS);
083    
084        public static final ImmutableSet<KtSingleValueToken> COMPARISON_OPERATIONS =
085                ImmutableSet.of(KtTokens.LT, KtTokens.GT, KtTokens.LTEQ, KtTokens.GTEQ);
086    
087        public static final ImmutableSet<KtSingleValueToken> EQUALS_OPERATIONS =
088                ImmutableSet.of(KtTokens.EQEQ, KtTokens.EXCLEQ);
089    
090        public static final ImmutableSet<KtSingleValueToken> IDENTITY_EQUALS_OPERATIONS =
091                ImmutableSet.of(KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ);
092    
093        public static final ImmutableSet<KtSingleValueToken> IN_OPERATIONS =
094                ImmutableSet.<KtSingleValueToken>of(KtTokens.IN_KEYWORD, KtTokens.NOT_IN);
095    
096        public static final ImmutableBiMap<KtSingleValueToken, Name> ASSIGNMENT_OPERATIONS = ImmutableBiMap.<KtSingleValueToken, Name>builder()
097                .put(KtTokens.MULTEQ, TIMES_ASSIGN)
098                .put(KtTokens.DIVEQ, DIV_ASSIGN)
099                .put(KtTokens.PERCEQ, MOD_ASSIGN)
100                .put(KtTokens.PLUSEQ, PLUS_ASSIGN)
101                .put(KtTokens.MINUSEQ, MINUS_ASSIGN)
102                .build();
103    
104        public static final ImmutableBiMap<KtSingleValueToken, KtSingleValueToken> ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableBiMap.<KtSingleValueToken, KtSingleValueToken>builder()
105                .put(KtTokens.MULTEQ, KtTokens.MUL)
106                .put(KtTokens.DIVEQ, KtTokens.DIV)
107                .put(KtTokens.PERCEQ, KtTokens.PERC)
108                .put(KtTokens.PLUSEQ, KtTokens.PLUS)
109                .put(KtTokens.MINUSEQ, KtTokens.MINUS)
110                .build();
111    
112        public static final ImmutableBiMap<KtSingleValueToken, Name> BOOLEAN_OPERATIONS = ImmutableBiMap.<KtSingleValueToken, Name>builder()
113                 .put(KtTokens.ANDAND, AND)
114                 .put(KtTokens.OROR, OR)
115                 .build();
116    
117        public static final ImmutableSet<Name> CONVENTION_NAMES = ImmutableSet.<Name>builder()
118                .add(GET, SET, INVOKE, CONTAINS, ITERATOR, NEXT, HAS_NEXT, EQUALS, COMPARE_TO, GET_VALUE, SET_VALUE)
119                .addAll(UNARY_OPERATION_NAMES.values())
120                .addAll(BINARY_OPERATION_NAMES.values())
121                .addAll(ASSIGNMENT_OPERATIONS.values())
122                .build();
123    
124        @Nullable
125        public static Name getNameForOperationSymbol(@NotNull KtToken token) {
126            return getNameForOperationSymbol(token, true, true);
127        }
128    
129        @Nullable
130        public static Name getNameForOperationSymbol(@NotNull KtToken token, boolean unaryOperations, boolean binaryOperations) {
131            Name name;
132    
133            if (binaryOperations) {
134                name = BINARY_OPERATION_NAMES.get(token);
135                if (name != null) return name;
136            }
137    
138            if (unaryOperations) {
139                name = UNARY_OPERATION_NAMES.get(token);
140                if (name != null) return name;
141            }
142    
143            name = ASSIGNMENT_OPERATIONS.get(token);
144            if (name != null) return name;
145            if (COMPARISON_OPERATIONS.contains(token)) return COMPARE_TO;
146            if (EQUALS_OPERATIONS.contains(token)) return EQUALS;
147            if (IN_OPERATIONS.contains(token)) return CONTAINS;
148            return null;
149        }
150    
151        public static boolean isConventionName(@NotNull Name name) {
152            return CONVENTION_NAMES.contains(name) || COMPONENT_REGEX.matches(name.asString());
153        }
154    }