1 /* <lambda>null2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.protolog.tool 18 19 import com.android.internal.protolog.common.LogLevel 20 import com.github.javaparser.ast.CompilationUnit 21 import com.github.javaparser.ast.ImportDeclaration 22 import com.github.javaparser.ast.expr.BinaryExpr 23 import com.github.javaparser.ast.expr.Expression 24 import com.github.javaparser.ast.expr.StringLiteralExpr 25 import java.util.UUID 26 27 object CodeUtils { 28 /** 29 * Returns a stable hash of a string. 30 * We reimplement String::hashCode() for readability reasons. 31 */ 32 fun hash( 33 position: String, 34 messageString: String, 35 logLevel: LogLevel, 36 logGroup: LogGroup 37 ): Long { 38 val fullStringIdentifier = position + messageString + logLevel.name + logGroup.name 39 return UUID.nameUUIDFromBytes(fullStringIdentifier.toByteArray()).mostSignificantBits 40 } 41 42 fun checkWildcardStaticImported(code: CompilationUnit, className: String, fileName: String) { 43 code.findAll(ImportDeclaration::class.java) 44 .forEach { im -> 45 if (im.isStatic && im.isAsterisk && im.name.toString() == className) { 46 throw IllegalImportException("Wildcard static imports of $className " + 47 "methods are not supported.", ParsingContext(fileName, im)) 48 } 49 } 50 } 51 52 fun isClassImportedOrSamePackage(code: CompilationUnit, className: String): Boolean { 53 val packageName = className.substringBeforeLast('.') 54 return code.packageDeclaration.isPresent && 55 code.packageDeclaration.get().nameAsString == packageName || 56 code.findAll(ImportDeclaration::class.java) 57 .any { im -> 58 !im.isStatic && 59 ((!im.isAsterisk && im.name.toString() == className) || 60 (im.isAsterisk && im.name.toString() == packageName)) 61 } 62 } 63 64 fun staticallyImportedMethods(code: CompilationUnit, className: String): Set<String> { 65 return code.findAll(ImportDeclaration::class.java) 66 .filter { im -> 67 im.isStatic && 68 im.name.toString().substringBeforeLast('.') == className 69 } 70 .map { im -> im.name.toString().substringAfterLast('.') }.toSet() 71 } 72 73 fun concatMultilineString(expr: Expression, context: ParsingContext): String { 74 return when (expr) { 75 is StringLiteralExpr -> expr.asString() 76 is BinaryExpr -> when { 77 expr.operator == BinaryExpr.Operator.PLUS -> 78 concatMultilineString(expr.left, context) + 79 concatMultilineString(expr.right, context) 80 else -> throw InvalidProtoLogCallException( 81 "expected a string literal " + 82 "or concatenation of string literals, got: $expr", context) 83 } 84 else -> throw InvalidProtoLogCallException("expected a string literal " + 85 "or concatenation of string literals, got: $expr", context) 86 } 87 } 88 } 89