001package eu.cqse.check.framework.util; 002 003import static eu.cqse.check.framework.scanner.ETokenType.AUTO; 004import static eu.cqse.check.framework.scanner.ETokenType.BOOL; 005import static eu.cqse.check.framework.scanner.ETokenType.CHAR; 006import static eu.cqse.check.framework.scanner.ETokenType.DOT; 007import static eu.cqse.check.framework.scanner.ETokenType.DOUBLE; 008import static eu.cqse.check.framework.scanner.ETokenType.FLOAT; 009import static eu.cqse.check.framework.scanner.ETokenType.ID; 010import static eu.cqse.check.framework.scanner.ETokenType.IDENTIFIER; 011import static eu.cqse.check.framework.scanner.ETokenType.INT; 012import static eu.cqse.check.framework.scanner.ETokenType.LONG; 013import static eu.cqse.check.framework.scanner.ETokenType.SCOPE; 014import static eu.cqse.check.framework.scanner.ETokenType.SHORT; 015import static eu.cqse.check.framework.scanner.ETokenType.SIGNED; 016import static eu.cqse.check.framework.scanner.ETokenType.UNSIGNED; 017import static eu.cqse.check.framework.scanner.ETokenType.VOID; 018 019import java.util.EnumSet; 020import java.util.List; 021import java.util.Set; 022import java.util.stream.Collectors; 023 024import org.conqat.lib.commons.collections.CollectionUtils; 025 026import eu.cqse.check.framework.scanner.ELanguage; 027import eu.cqse.check.framework.scanner.ETokenType; 028import eu.cqse.check.framework.scanner.IToken; 029import eu.cqse.check.framework.shallowparser.SubTypeNames; 030import eu.cqse.check.framework.shallowparser.TokenStreamTextUtils; 031import eu.cqse.check.framework.shallowparser.TokenStreamUtils; 032import eu.cqse.check.framework.shallowparser.framework.EShallowEntityType; 033import eu.cqse.check.framework.shallowparser.framework.ShallowEntity; 034import eu.cqse.check.framework.util.variable.CLikeVariableUseExtractor; 035 036/** Language feature parser for Objective-C. */ 037public class ObjcLanguageFeatureParser extends CLikeLanguageFeatureParserBase { 038 039 /** All token types that can be used to specify a type. */ 040 private static final EnumSet<ETokenType> ADDITIONAL_TYPE_TOKENS = EnumSet.of(IDENTIFIER, ID, AUTO); 041 042 /** All token types that can be used to specify a type. */ 043 private static final EnumSet<ETokenType> PRIMITIVE_TYPE_TOKENS = EnumSet.of(SIGNED, UNSIGNED, BOOL, CHAR, SHORT, 044 INT, LONG, FLOAT, DOUBLE, VOID); 045 046 /** All token types that can be used as identifier. */ 047 private static final EnumSet<ETokenType> VALID_IDENTIFIERS = EnumSet.of(IDENTIFIER, ETokenType.OPERATOR); 048 049 /** Names of classes that count as generic exceptions. */ 050 private static final Set<String> GENERIC_EXCEPTION_NAMES = CollectionUtils.asHashSet("NSException", "id"); 051 052 ObjcLanguageFeatureParser() { 053 super(ELanguage.OBJECTIVE_C, VALID_IDENTIFIERS, PRIMITIVE_TYPE_TOKENS, ADDITIONAL_TYPE_TOKENS, SCOPE, ".", 054 new CLikeVariableUseExtractor(EnumSet.of(DOT), VALID_IDENTIFIERS)); 055 super.variableSplitType = ETokenType.COLON; 056 } 057 058 @Override 059 public boolean isImport(ShallowEntity entity) { 060 return entity.getType() == EShallowEntityType.META && entity.getSubtype().equals(SubTypeNames.AT_IMPORT); 061 } 062 063 @Override 064 public String getImportName(ShallowEntity entity) { 065 return TokenStreamTextUtils.concatTokenTexts( 066 TokenStreamUtils.tokensBetween(entity.ownStartTokens(), ETokenType.IMPORT, ETokenType.SEMICOLON)); 067 } 068 069 /** 070 * Determines whether the given class name represents a generic exception. 071 */ 072 public boolean isGenericExceptionClass(String className) { 073 return GENERIC_EXCEPTION_NAMES.contains(className); 074 } 075 076 /** 077 * Returns a list of parameter tokens for the given tokensAfterMethodName. 078 * Example for <code> 079 * -(void)foo1:(int) x1:(int) x2 </code>. Returns 080 * <code>[int, x1, :, int, x2]</code>. 081 */ 082 083 @Override 084 public List<IToken> extractParameterTokens(List<IToken> methodStartTokens) { 085 086 // Creating a Sublist of tokensAfterMethodName between COLON ":" and LBRACE"{". 087 List<IToken> tokensAfterMethodName = TokenStreamUtils.tokensBetween(methodStartTokens, ETokenType.COLON, 088 ETokenType.LBRACE); 089 return tokensAfterMethodName.stream() 090 .filter(x -> x.getType() != ETokenType.LPAREN && x.getType() != ETokenType.RPAREN) 091 .collect(Collectors.toList()); 092 093 } 094 095}