private def basename()

in scrooge-generator/src/main/scala/com/twitter/scrooge/backend/ServiceTemplate.scala [247:443]


  private def basename(fqdn: String): String = fqdn.split('.').last

  def serviceDict(
    service: Service,
    namespace: Identifier,
    includes: Seq[Include],
    options: Set[ServiceOption],
    genAdapt: Boolean
  ): Dictionary = {
    val withFinagle = options.contains(WithFinagle)
    val withAsClosable = options.contains(WithAsClosable)
    lazy val computeInheritedFunctions: Service => (Seq[Dictionary], Seq[Dictionary]) = { service =>
      {
        // For service-per-endpoint, we generate a class with a value for each method, so
        // method names must be unique.
        val deduper = new NameDeduplicator()
        val inheritedFunctions: Seq[Dictionary] =
          // Note: inherited functions must be deduped first, so we walk the parent chain
          // from the topmost parent down (hence the reverse).
          resolvedDoc
            .resolveParentServices(service, namespaceLanguage, defaultNamespace)
            .reverse
            .flatMap { result: ResolvedService =>
              result.service.functions.map { function =>
                val camelCase = function.funcName.toCamelCase
                Dictionary(
                  "ParentServiceName" -> genID(result.serviceID),
                  "funcName" -> genID(camelCase),
                  "dedupedFuncName" -> genID(deduper.dedupe(camelCase)),
                  "funcObjectName" -> genID(functionObjectName(function)),
                  "withFuncName" -> genID(deduper.dedupe(function.funcName.toTitleCase))
                )
              }
            }
        val ownFunctions: Seq[Dictionary] = service.functions.map { function =>
          functionDictionary(function, Some("Future")) ++= (
            "ParentServiceName" -> v("self"),
            "dedupedFuncName" -> genID(deduper.dedupe(function.funcName.toCamelCase)),
            "withFuncName" -> genID(deduper.dedupe(function.funcName.toTitleCase)),
            "hasValidationAnnotation" -> v(function.args.exists(hasValidationAnnotation))
          )
        }
        (inheritedFunctions, ownFunctions)
      }
    }

    val pkg = genID(namespace)
    val pkgName = v(basename(pkg.toData))

    Dictionary(
      "function" -> v(templates("function")),
      "package" -> pkg,
      "packageName" -> pkgName,
      "ServiceName" -> genID(service.sid.toTitleCase),
      "docstring" -> v(service.docstring.getOrElse("")),
      "syncParent" -> v(service.parent.map { p => genID(getServiceParentID(p)).append(".Iface") }),
      "parent" -> v(service.parent.map { p => genQualifiedID(getServiceParentID(p), namespace) }),
      "methodPerEndpointParent" -> v(service.parent.map { p =>
        genQualifiedID(getServiceParentID(p), namespace).append(".MethodPerEndpoint")
      }),
      "futureIfaceParent" -> v(service.parent.map { p =>
        genQualifiedID(getServiceParentID(p), namespace).append(".FutureIface")
      }),
      "genericParent" -> service.parent
        .map { p => genQualifiedID(getServiceParentID(p), namespace).append(".MethodPerEndpoint") }
        .getOrElse(v("_root_.com.twitter.finagle.thrift.ThriftService")),
      "syncFunctions" -> v(service.functions.map { f => functionDictionary(f, None) }),
      "asyncFunctions" -> v(service.functions.map { f => functionDictionary(f, Some("Future")) }),
      "genericFunctions" -> v(service.functions.map { f => functionDictionary(f, Some("MM")) }),
      "struct" -> v(templates("struct")),
      "hasValidationAnnotation" -> v(
        service.functions.exists(f => f.args.exists(hasValidationAnnotation))),
      "serverValidationMixin" -> v(templates("serverValidationMixin")),
      "serverValidationMethods" -> v(service.functions.map { f =>
        Dictionary(
          "args" -> v(f.args.map { arg =>
            Dictionary(
              "arg" -> genID(arg.sid),
              "typeParameter" -> genFieldType(arg)
            )
          }),
          "argsWithValidations" -> {
            val validatedArg = f.args.filter(hasValidationAnnotation)
            v(validatedArg.zipWithIndex.map {
              case (arg, index) =>
                Dictionary(
                  "violationArg" -> v(genID(arg.sid) + "Violations"),
                  "arg" -> genID(arg.sid),
                  "firstArg" -> v(index == 0),
                  "middleArgs" -> v(index > 0 && index < validatedArg.size - 1),
                  "lastArg" -> v(index == validatedArg.size - 1)
                )
            })
          },
          "oneArg" -> v(f.args.filter(hasValidationAnnotation).size == 1),
          "typeName" -> genType(f.funcType),
          "funcName" -> genID(f.funcName.toCamelCase),
          "argNames" -> {
            val code = f.args
              .map { field => genID(field.sid).toData }
              .mkString(", ")
            v(code)
          },
          "hasValidationAnnotation" -> v(f.args.exists(hasValidationAnnotation)),
          "violationReturningFuncName" -> genID(
            f.funcName.toTitleCase.prepend("violationReturning")),
          "fieldParams" -> genFieldParams(
            f.args
          ) // A list of parameters with types: (a: A, b: B...)
        )
      }),
      "thriftFunctions" -> v(service.functions.map { f =>
        Dictionary(
          "functionArgsStruct" ->
            v(structDict(functionArgsStruct(f), Some(namespace), includes, options, genAdapt)),
          "internalResultStruct" -> {
            val functionResult = resultStruct(f)
            v(
              structDict(functionResult, Some(namespace), includes, options, genAdapt) +
                Dictionary(
                  "successFieldType" -> getSuccessType(functionResult),
                  "successFieldValue" -> getSuccessValue(functionResult),
                  "exceptionValues" -> getExceptionFields(functionResult)
                )
            )
          },
          "annotations" -> TemplateGenerator.renderPairs(f.annotations),
          "funcObjectName" -> genID(functionObjectName(f)),
          "unwrapArgs" -> v(unwrapArgs(f.args.length)),
          "hasValidationAnnotation" -> v(f.args.exists(hasValidationAnnotation))
        ) + functionDictionary(f, Some("Future"))
      }),
      "hasThriftFunctions" -> v(service.functions.nonEmpty),
      "finagleClients" -> v(
        if (withFinagle) Seq(finagleClient(service, namespace, withAsClosable)) else Seq()
      ),
      "finagleServices" -> v(
        if (withFinagle) Seq(finagleService(service, namespace)) else Seq()
      ),
      // scalac 2.11 fails to compile classes with more than 254 method arguments
      // due to https://issues.scala-lang.org/browse/SI-7324
      // We skip generation of ServiceIfaces for thrift services with 255+ methods.
      "generateServiceIface" -> {
        val numParentFunctions = resolvedDoc
          .collectParentServices(service)
          .map {
            case (_, service) => service.functions.length
          }
          .sum
        val totalFunctions = service.functions.length + numParentFunctions
        v(totalFunctions <= 254)
      },
      "withFinagle" -> v(withFinagle),
      "inheritedFunctions" -> {
        val (inheritedParentFunctions, ownFunctions) = computeInheritedFunctions(service)
        v(ownFunctions ++ inheritedParentFunctions)
      },
      "inheritedParentFunctions" -> {
        val (inheritedParentFunctions, _) = computeInheritedFunctions(service)
        v(inheritedParentFunctions)
      },
      "ownFunctions" -> {
        val (_, ownFunctions) = computeInheritedFunctions(service)
        v(ownFunctions)
      },
      "annotations" -> TemplateGenerator.renderPairs(service.annotations),
      "withAsClosable" -> v(withAsClosable),
      "methodFilter" -> v(templates("methodFilter")),
      "methodFilters" -> v(service.functions map { f =>
        Dictionary(
          "methodSvcNameForCompile" -> genID(f.funcName.toCamelCase),
          "methodSvcNameForWire" -> v(f.originalName),
          "funcObjectName" -> genID(functionObjectName(f)),
          "argNames" ->
            v(
              f.args
                .map { field => "args." + genID(field.sid).toData }
                .mkString(", ")
            ),
          "typeName" -> genType(f.funcType),
          "resultNamedArg" ->
            v(if (f.funcType != Void && f.funcType != OnewayVoid) "success = Some(resTry.apply())"
            else ""),
          "exceptions" -> v(f.throws.zipWithIndex map {
            case (t, index) =>
              Dictionary(
                "exceptionType" -> genType(t.fieldType),
                "fieldName" -> genID(t.sid),
                "first" -> v(index == 0),
                "last" -> v(index == f.throws.size - 1)
              )
          }),
          "hasExceptions" -> v(f.throws.nonEmpty)
        )
      })
    )
  }