output: #fixed code
                                  private TypeUsage getTypeConcrete(Node node, boolean solveLambdas) {
          if (node == null) throw new IllegalArgumentException();
          if (node instanceof NameExpr) {
              NameExpr nameExpr = (NameExpr) node;
              logger.finest("getType on name expr " + node);
              Optional<Value> value = new SymbolSolver(typeSolver).solveSymbolAsValue(nameExpr.getName(), nameExpr);
              if (!value.isPresent()){
                  throw new UnsolvedSymbolException("FOO Solving "+node, nameExpr.getName());
              } else {
                  return value.get().getUsage();
              }
          } else if (node instanceof MethodCallExpr) {
              logger.finest("getType on method call " + node);
              // first solve the method
              MethodUsage ref = new JavaParserFacade(typeSolver).solveMethodAsUsage((MethodCallExpr) node);
              logger.finest("getType on method call " + node + " resolved to " + ref);
              logger.finest("getType on method call " + node + " return type is " + ref.returnType());
              return ref.returnType();
              // the type is the return type of the method
          } else if (node instanceof LambdaExpr) {
              if (node.getParentNode() instanceof MethodCallExpr) {
                  MethodCallExpr callExpr = (MethodCallExpr) node.getParentNode();
                  int pos = JavaParserSymbolDeclaration.getParamPos(node);
                  SymbolReference<MethodDeclaration> refMethod = new JavaParserFacade(typeSolver).solve(callExpr);
                  if (!refMethod.isSolved()) {
                      throw new UnsolvedSymbolException(callExpr.getName());
                  }
                  logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName());
                  //logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos));
                  if (solveLambdas) {
                      TypeUsage result = refMethod.getCorrespondingDeclaration().getParam(pos).getType(typeSolver);
                      // We need to replace the type variables
                      result = result.solveGenericTypes(JavaParserFactory.getContext(node), typeSolver);
                      return result;
                  } else {
                      return refMethod.getCorrespondingDeclaration().getParam(pos).getType(typeSolver);
                  }
                  //System.out.println("LAMBDA " + node.getParentNode());
                  //System.out.println("LAMBDA CLASS " + node.getParentNode().getClass().getCanonicalName());
                  //TypeUsage typeOfMethod = new JavaParserFacade(typeSolver).getType(node.getParentNode());
                  //throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value");
              } else {
                  throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value");
              }
          } else if (node instanceof VariableDeclarator) {
              if (node.getParentNode() instanceof FieldDeclaration) {
                  FieldDeclaration parent = (FieldDeclaration) node.getParentNode();
                  return new JavaParserFacade(typeSolver).convertToUsage(parent.getType(), parent);
              } else if (node.getParentNode() instanceof VariableDeclarationExpr) {
                  VariableDeclarationExpr parent = (VariableDeclarationExpr) node.getParentNode();
                  return new JavaParserFacade(typeSolver).convertToUsage(parent.getType(), parent);
              } else {
                  throw new UnsupportedOperationException(node.getParentNode().getClass().getCanonicalName());
              }
          } else if (node instanceof Parameter) {
              Parameter parameter = (Parameter)node;
              if (parameter.getType() instanceof UnknownType){
                  throw new IllegalStateException("Parameter has unknown type: " + parameter);
              }
              return new JavaParserFacade(typeSolver).convertToUsage(parameter.getType(), parameter);
          } else if (node instanceof FieldAccessExpr) {
              FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) node;
              // We should understand if this is a static access
              try {
                  Optional<Value> value = new SymbolSolver(typeSolver).solveSymbolAsValue(fieldAccessExpr.getField(), fieldAccessExpr);
                  if (value.isPresent()) {
                      return value.get().getUsage();
                  } else {
                      throw new UnsolvedSymbolException(fieldAccessExpr.getField());
                  }
              } catch (UnsolvedSymbolException e){
                  // Sure, it was not found as value because maybe it is a type and this is a static access
                  if (fieldAccessExpr.getScope() instanceof NameExpr){
                      NameExpr staticValue = (NameExpr)fieldAccessExpr.getScope();
                      SymbolReference<TypeDeclaration> typeAccessedStatically = JavaParserFactory.getContext(fieldAccessExpr).solveType(staticValue.toString(), typeSolver);
                      if (!typeAccessedStatically.isSolved()) {
                          throw e;
                      } else {
                          // TODO here maybe we have to substitute type parameters
                          return typeAccessedStatically.getCorrespondingDeclaration().getField(fieldAccessExpr.getField(), typeSolver).getType(typeSolver);
                      }
                  } else {
                      throw e;
                  }
  
              }
          } else if (node instanceof ObjectCreationExpr) {
              ObjectCreationExpr objectCreationExpr = (ObjectCreationExpr) node;
              TypeUsage typeUsage = new JavaParserFacade(typeSolver).convertToUsage(objectCreationExpr.getType(), node);
              return typeUsage;
          } else if (node instanceof NullLiteralExpr) {
              return new NullTypeUsage();
          } else if (node instanceof BooleanLiteralExpr) {
              return PrimitiveTypeUsage.BOOLEAN;
          } else if (node instanceof IntegerLiteralExpr) {
              return PrimitiveTypeUsage.INT;
          } else if (node instanceof LongLiteralExpr) {
              return PrimitiveTypeUsage.LONG;
          } else if (node instanceof CharLiteralExpr) {
              return PrimitiveTypeUsage.CHAR;
          } else if (node instanceof StringLiteralExpr) {
              return new TypeUsageOfTypeDeclaration(new JreTypeSolver().solveType("java.lang.String"));
          } else if (node instanceof UnaryExpr) {
              UnaryExpr unaryExpr = (UnaryExpr)node;
              switch (unaryExpr.getOperator()) {
                  case negative:
                  case positive:
                      return getTypeConcrete(unaryExpr.getExpr(), solveLambdas);
                  case not:
                      return PrimitiveTypeUsage.BOOLEAN;
                  case posIncrement:
                  case preIncrement:
                  case preDecrement:
                  case posDecrement:
                      return getTypeConcrete(unaryExpr.getExpr(), solveLambdas);
                  default:
                      throw new UnsupportedOperationException(unaryExpr.getOperator().name());
              }
          } else if (node instanceof BinaryExpr) {
              BinaryExpr binaryExpr = (BinaryExpr) node;
              switch (binaryExpr.getOperator()) {
                  case plus:
                  case minus:
                      return getTypeConcrete(binaryExpr.getLeft(), solveLambdas);
                  case lessEquals:
                  case less:
                  case greater:
                  case greaterEquals:
                  case equals:
                  case notEquals:
                  case or:
                  case and:
                      return PrimitiveTypeUsage.BOOLEAN;
                  case binAnd:
                  case binOr:
                      return getTypeConcrete(binaryExpr.getLeft(), solveLambdas);
                  default:
                      throw new UnsupportedOperationException("FOO " +binaryExpr.getOperator().name());
              }
          } else if (node instanceof VariableDeclarationExpr) {
              VariableDeclarationExpr expr = (VariableDeclarationExpr)node;
              return convertToUsage(expr.getType(), JavaParserFactory.getContext(node));
          } else if (node instanceof InstanceOfExpr) {
              return PrimitiveTypeUsage.BOOLEAN;
          } else if (node instanceof EnclosedExpr) {
              EnclosedExpr enclosedExpr = (EnclosedExpr)node;
              return getTypeConcrete(enclosedExpr.getInner(), solveLambdas);
          } else if (node instanceof CastExpr) {
              CastExpr enclosedExpr = (CastExpr)node;
              return convertToUsage(enclosedExpr.getType(), JavaParserFactory.getContext(node));
          } else if (node instanceof AssignExpr) {
              AssignExpr assignExpr = (AssignExpr) node;
              return getTypeConcrete(assignExpr.getTarget(), solveLambdas);
          } else if (node instanceof ThisExpr) {
              return new TypeUsageOfTypeDeclaration(getTypeDeclaration(findContainingTypeDecl(node)));
          } else if (node instanceof ConditionalExpr) {
              ConditionalExpr conditionalExpr = (ConditionalExpr)node;
              return getTypeConcrete(conditionalExpr.getThenExpr(), solveLambdas);
          } else if (node instanceof ArrayCreationExpr) {
              ArrayCreationExpr arrayCreationExpr = (ArrayCreationExpr)node;
              return convertToUsage(arrayCreationExpr.getType(), JavaParserFactory.getContext(node));
          } else {
              throw new UnsupportedOperationException(node.getClass().getCanonicalName());
          }
      }
input: #vulnerable code 
                                  private TypeUsage getTypeConcrete(Node node, boolean solveLambdas) {
          if (node == null) throw new IllegalArgumentException();
          if (node instanceof NameExpr) {
              NameExpr nameExpr = (NameExpr) node;
              logger.finest("getType on name expr " + node);
              Optional<Value> value = new SymbolSolver(typeSolver).solveSymbolAsValue(nameExpr.getName(), nameExpr);
              if (!value.isPresent()){
                  throw new UnsolvedSymbolException("Solving "+node, nameExpr.getName());
              } else {
                  return value.get().getUsage();
              }
          } else if (node instanceof MethodCallExpr) {
              logger.finest("getType on method call " + node);
              // first solve the method
              MethodUsage ref = new JavaParserFacade(typeSolver).solveMethodAsUsage((MethodCallExpr) node);
              logger.finest("getType on method call " + node + " resolved to " + ref);
              logger.finest("getType on method call " + node + " return type is " + ref.returnType());
              return ref.returnType();
              // the type is the return type of the method
          } else if (node instanceof LambdaExpr) {
              if (node.getParentNode() instanceof MethodCallExpr) {
                  MethodCallExpr callExpr = (MethodCallExpr) node.getParentNode();
                  int pos = JavaParserSymbolDeclaration.getParamPos(node);
                  SymbolReference<MethodDeclaration> refMethod = new JavaParserFacade(typeSolver).solve(callExpr);
                  if (!refMethod.isSolved()) {
                      throw new UnsolvedSymbolException(callExpr.getName());
                  }
                  logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName());
                  //logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos));
                  if (solveLambdas) {
                      TypeUsage result = refMethod.getCorrespondingDeclaration().getParam(pos).getType(typeSolver);
                      // We need to replace the type variables
                      result = result.solveGenericTypes(JavaParserFactory.getContext(node), typeSolver);
                      return result;
                  } else {
                      return refMethod.getCorrespondingDeclaration().getParam(pos).getType(typeSolver);
                  }
                  //System.out.println("LAMBDA " + node.getParentNode());
                  //System.out.println("LAMBDA CLASS " + node.getParentNode().getClass().getCanonicalName());
                  //TypeUsage typeOfMethod = new JavaParserFacade(typeSolver).getType(node.getParentNode());
                  //throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value");
              } else {
                  throw new UnsupportedOperationException("The type of a lambda expr depends on the position and its return value");
              }
          } else if (node instanceof VariableDeclarator) {
              if (node.getParentNode() instanceof FieldDeclaration) {
                  FieldDeclaration parent = (FieldDeclaration) node.getParentNode();
                  return new JavaParserFacade(typeSolver).convertToUsage(parent.getType(), parent);
              } else if (node.getParentNode() instanceof VariableDeclarationExpr) {
                  VariableDeclarationExpr parent = (VariableDeclarationExpr) node.getParentNode();
                  return new JavaParserFacade(typeSolver).convertToUsage(parent.getType(), parent);
              } else {
                  throw new UnsupportedOperationException(node.getParentNode().getClass().getCanonicalName());
              }
          } else if (node instanceof Parameter) {
              Parameter parameter = (Parameter)node;
              if (parameter.getType() instanceof UnknownType){
                  throw new IllegalStateException("Parameter has unknown type: " + parameter);
              }
              return new JavaParserFacade(typeSolver).convertToUsage(parameter.getType(), parameter);
          } else if (node instanceof FieldAccessExpr) {
              FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) node;
              // We should understand if this is a static access
              try {
                  Optional<Value> value = new SymbolSolver(typeSolver).solveSymbolAsValue(fieldAccessExpr.getField(), fieldAccessExpr);
                  if (value.isPresent()) {
                      return value.get().getUsage();
                  } else {
                      throw new UnsolvedSymbolException(fieldAccessExpr.getField());
                  }
              } catch (UnsolvedSymbolException e){
                  // Sure, it was not found as value because maybe it is a type and this is a static access
                  if (fieldAccessExpr.getScope() instanceof NameExpr){
                      NameExpr staticValue = (NameExpr)fieldAccessExpr.getScope();
                      SymbolReference<TypeDeclaration> typeAccessedStatically = JavaParserFactory.getContext(fieldAccessExpr).solveType(staticValue.toString(), typeSolver);
                      if (!typeAccessedStatically.isSolved()) {
                          throw e;
                      } else {
                          // TODO here maybe we have to substitute type parameters
                          return typeAccessedStatically.getCorrespondingDeclaration().getField(fieldAccessExpr.getField(), typeSolver).getType(typeSolver);
                      }
                  } else {
                      throw e;
                  }
  
              }
          } else if (node instanceof ObjectCreationExpr) {
              ObjectCreationExpr objectCreationExpr = (ObjectCreationExpr) node;
              TypeUsage typeUsage = new JavaParserFacade(typeSolver).convertToUsage(objectCreationExpr.getType(), node);
              return typeUsage;
          } else if (node instanceof NullLiteralExpr) {
              return new NullTypeUsage();
          } else if (node instanceof BooleanLiteralExpr) {
              return PrimitiveTypeUsage.BOOLEAN;
          } else if (node instanceof IntegerLiteralExpr) {
              return PrimitiveTypeUsage.INT;
          } else if (node instanceof LongLiteralExpr) {
              return PrimitiveTypeUsage.LONG;
          } else if (node instanceof CharLiteralExpr) {
              return PrimitiveTypeUsage.CHAR;
          } else if (node instanceof StringLiteralExpr) {
              return new TypeUsageOfTypeDeclaration(new JreTypeSolver().solveType("java.lang.String"));
          } else if (node instanceof UnaryExpr) {
              UnaryExpr unaryExpr = (UnaryExpr)node;
              switch (unaryExpr.getOperator()) {
                  case negative:
                  case positive:
                      return getTypeConcrete(unaryExpr.getExpr(), solveLambdas);
                  case not:
                      return PrimitiveTypeUsage.BOOLEAN;
                  case posIncrement:
                  case preIncrement:
                  case preDecrement:
                  case posDecrement:
                      return getTypeConcrete(unaryExpr.getExpr(), solveLambdas);
                  default:
                      throw new UnsupportedOperationException(unaryExpr.getOperator().name());
              }
          } else if (node instanceof BinaryExpr) {
              BinaryExpr binaryExpr = (BinaryExpr) node;
              switch (binaryExpr.getOperator()) {
                  case plus:
                  case minus:
                      return getTypeConcrete(binaryExpr.getLeft(), solveLambdas);
                  case lessEquals:
                  case less:
                  case greater:
                  case greaterEquals:
                  case equals:
                  case notEquals:
                  case or:
                  case and:
                      return PrimitiveTypeUsage.BOOLEAN;
                  case binAnd:
                  case binOr:
                      return getTypeConcrete(binaryExpr.getLeft(), solveLambdas);
                  default:
                      throw new UnsupportedOperationException("FOO " +binaryExpr.getOperator().name());
              }
          } else if (node instanceof VariableDeclarationExpr) {
              VariableDeclarationExpr expr = (VariableDeclarationExpr)node;
              return convertToUsage(expr.getType(), JavaParserFactory.getContext(node));
          } else if (node instanceof InstanceOfExpr) {
              return PrimitiveTypeUsage.BOOLEAN;
          } else if (node instanceof EnclosedExpr) {
              EnclosedExpr enclosedExpr = (EnclosedExpr)node;
              return getTypeConcrete(enclosedExpr.getInner(), solveLambdas);
          } else if (node instanceof CastExpr) {
              CastExpr enclosedExpr = (CastExpr)node;
              return convertToUsage(enclosedExpr.getType(), JavaParserFactory.getContext(node));
          } else if (node instanceof AssignExpr) {
              AssignExpr assignExpr = (AssignExpr) node;
              return getTypeConcrete(assignExpr.getTarget(), solveLambdas);
          } else if (node instanceof ThisExpr) {
              return new TypeUsageOfTypeDeclaration(getTypeDeclaration(findContainingTypeDecl(node)));
          } else if (node instanceof ConditionalExpr) {
              ConditionalExpr conditionalExpr = (ConditionalExpr)node;
              return getTypeConcrete(conditionalExpr.getThenExpr(), solveLambdas);
          } else if (node instanceof ArrayCreationExpr) {
              ArrayCreationExpr arrayCreationExpr = (ArrayCreationExpr)node;
              return convertToUsage(arrayCreationExpr.getType(), JavaParserFactory.getContext(node));
          } else {
              throw new UnsupportedOperationException(node.getClass().getCanonicalName());
          }
      } 
                              #location 161 
                              #vulnerability type NULL_DEREFERENCE