Exemplo n.º 1
0
/**
 * Transforms a ScalarField type into its corresponding Flow AST node.
 */
function transformScalarField(type: GraphQLType): Annotation {
  if (type instanceof GraphQLScalarType) {
    switch (type.name) {
      case 'Color':
      case 'File':
      case 'ID':
      case 'String':
      case 'Url':
        return t.stringTypeAnnotation();
      case 'Float':
      case 'Int':
      case 'Time':
        return t.numberTypeAnnotation();
      case 'Boolean':
        return t.booleanTypeAnnotation();
      default:
        // Fallback to `any` for custom scalar types.
        return t.anyTypeAnnotation();
    }
  } else if (type instanceof GraphQLEnumType) {
    const stringLiterals = type.getValues().map(({value}) => {
      const literal = t.stringLiteralTypeAnnotation();
      literal.value = value;
      return literal;
    });

    return t.unionTypeAnnotation(stringLiterals);
  } else {
    throw new Error(`Could not convert from GraphQL type ${type.toString()}`);
  }
}
Exemplo n.º 2
0
export function BinaryExpression(node) {
  let operator = node.operator;

  if (t.NUMBER_BINARY_OPERATORS.indexOf(operator) >= 0) {
    return t.numberTypeAnnotation();
  } else if (t.BOOLEAN_BINARY_OPERATORS.indexOf(operator) >= 0) {
    return t.booleanTypeAnnotation();
  } else if (operator === "+") {
    let right = this.get("right");
    let left  = this.get("left");

    if (left.isBaseType("number") && right.isBaseType("number")) {
      // both numbers so this will be a number
      return t.numberTypeAnnotation();
    } else if (left.isBaseType("string") || right.isBaseType("string")) {
      // one is a string so the result will be a string
      return t.stringTypeAnnotation();
    }

    // unsure if left and right are strings or numbers so stay on the safe side
    return t.unionTypeAnnotation([
      t.stringTypeAnnotation(),
      t.numberTypeAnnotation()
    ]);
  }
}
Exemplo n.º 3
0
function getTypeAnnotationBindingConstantViolations(path, name) {
  let binding = path.scope.getBinding(name);

  let types = [];
  path.typeAnnotation = t.unionTypeAnnotation(types);

  let functionConstantViolations = [];
  let constantViolations = getConstantViolationsBefore(binding, path, functionConstantViolations);

  let testType = getConditionalAnnotation(path, name);
  if (testType) {
    let testConstantViolations = getConstantViolationsBefore(binding, testType.ifStatement);

    // remove constant violations observed before the IfStatement
    constantViolations = constantViolations.filter((path) => testConstantViolations.indexOf(path) < 0);

    // clear current types and add in observed test type
    types.push(testType.typeAnnotation);
  }

  if (constantViolations.length) {
    // pick one constant from each scope which will represent the last possible
    // control flow path that it could've taken/been
    let rawConstantViolations = constantViolations.reverse();
    let visitedScopes = [];
    constantViolations = [];
    for (let violation of (rawConstantViolations: Array<NodePath>)) {
      let violationScope = violation.scope;
      if (visitedScopes.indexOf(violationScope) >= 0) continue;

      visitedScopes.push(violationScope);
      constantViolations.push(violation);

      if (violationScope === path.scope) {
        constantViolations = [violation];
        break;
      }
    }

    // add back on function constant violations since we can't track calls
    constantViolations = constantViolations.concat(functionConstantViolations);

    // push on inferred types of violated paths
    for (let violation of (constantViolations: Array<NodePath>)) {
      types.push(violation.getTypeAnnotation());
    }
  }

  if (types.length) {
    return t.createUnionTypeAnnotation(types);
  }
}