Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add project context to code completions #571

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

PhilKes
Copy link
Contributor

@PhilKes PhilKes commented May 17, 2024

WORK IN PROGRESS

This PR adds context to the code-completions.

Quite a few of the models support repository-level completions via special tokens:
CodeQwen 1.5
DeepSeek Coder
CodeGemma
StarCoder2

Consider this simple Java example from an old project of mine (movieland).
MovieUtils.java:

@Service
public class MovieUtils {
    private final MovieService movieService;

    public MovieUtils(MovieService movieService) {
        this.movieService = movieService;
    }
    public List<Movie> getMoviesSortedByPlaytime(String name) {
        return <CURSOR>
    }
     
}

Obviously in examples like this, the code-completion without context can not be of much help since the model doesnt know the contents of the MovieService or Movie class of my project.

Proposal

To get further context for a specific code-completion example we have to somehow parse the given code and then decide what other project files could be useful.
To do that, I am leveraging the IntelliJ OpenAPI's Program Structure Interface (PSI), which the IDEs use internally to parse the source code files.
IntelliJ provides a PSI implementation for every programming language they support (see e.g. Supported Languages, IntelliJ Modules, Other Bundles Plugins)
These are the steps to determine the context files for a java project:

  1. Determine the PsiElement at the cursor position (in the above example: PsiWhiteSpace)
  2. Find the closest parent PsiMethod or PsiClass (in the above example: PsiMethod:getMoviesSortedByPlaytime)
  3. Determine all PsiTypeElements that are used inside of that parent (e.g. method parameters, return value type, local variables) (in the above example: PsiTypeElement:Movie, PsiTypeElement:String)
  4. If the parent is a PsiMethod also class and static fields of the parent PsiClass are taken into account (see example movieService field) (in the above example: PsiTypeElement:MovieService)
  5. For all found PsiTypeElements the VirtualFile containing its source code is evaluated (only for project files, library or jdk files/classes are ignored) (in the above example: Movie.java, MovieService.java)
  6. The contents of the found VirtualFiles are prepended to the code-completion prompts according to the models' prompt formats for repository-level completions.

Results

I have tested the described example with all models that support repository-level completions and tried to accumulate the results here: Code_Completions_Context_Model Google Sheet. Be aware that I only tested the described scenario and did not do large test runs, the measurement were all done once to get a basic overview of the performance and the code quality ratings are purely subjective (system specs: Linux Mint 20.3 with AMD Ryzen 2700X + GTX 1070 8GB VRAM)

Note: I am not sure yet why the DeepSeekCoder 6.7b tests without context returned absolute jibberish

For all models I tested the code-completions as they were and then with the new context included.
As you can see in the spread sheet, the completions without context gave terrible results with method calls on the movieService instance that do not even exist.
The best result was achieved with CodeQwen 1.5 (IQ4_NL / Q_2_K) with context, which returned a great, working completion:

public List<Movie> getMoviesSortedByPlaytime(String name) {
    return movieService.queryAllMovies(name).stream() .sorted(Comparator.comparingLong(Movie::getLength
}

It found the correct method MovieService.queryAllMovies to use and also understood the Movie.length field is interpreted as its playtime.

Note: I disabled the code-completion from being stopped at "\n" for this test, but didn't increase the maxTokens

Advantages:

  • Much better completions in many scenarios
  • Some smaller models (e.g. DeepSeekCoder 1.3b-instruct.Q5_K_M) returned quite good results while still having a low response time (~2s)
  • Newer models such as CodeQwen 1.5 performs very good with context size up to 64k tokens (see https://qwenlm.github.io/blog/codeqwen1.5/#codeqwen-are-long-context-coders)
  • In theory we could also add library source code to the prompt since they can be evaluated with PSI as well. Since models are only trained on specific timestamps, this could be used to "keep them up-to-date" with newer library source code

Disadvantages:

  • Prompts have much more tokens (e.g. 131 without context vs 2024 with context), therefore also higher response times
  • Implementation to retrieve context is language specific (e.g. have to provide different implementation for Java, Python, JavaScript)

Open Questions

  • Which model is the best compromise between response time and completion quality?
  • Which level of depth should the context include?
  • Implement the context search for other languages than Java
  • Should the user have an option to include/exclude this automatic context for code-completions?

@@ -5,6 +5,13 @@
<depends>com.intellij.modules.platform</depends>
<depends>com.intellij.modules.lang</depends>
<depends optional="true" config-file="plugin-java.xml">com.intellij.modules.java</depends>
<depends optional="true" config-file="plugin-python.xml">com.intellij.modules.python</depends>
<!-- TODO-->
<!-- <depends optional="true" config-file="plugin-js.xml">JavaScript</depends>-->
Copy link
Contributor Author

@PhilKes PhilKes May 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These would be needed to implement a LanguagePsiParser for e.g. Python, JavaScript, PHP, ...
In the plugin-python.xml a PythonContextFinder service would be added, which would only be loaded if the user uses an IDE with Python support (e.g. PyCharm or IntelliJ with Python Plugin)

@PhilKes PhilKes marked this pull request as draft May 17, 2024 14:18
@PhilKes
Copy link
Contributor Author

PhilKes commented May 20, 2024

Another great thing about PSI, we can not only use IntelliJ's language support, IntellIJ Ultimate also offers e.g. a Spring API which is based on PSI. This offers the ability to access a CommonSpringModel which allows us to easily find e.g. Spring Beans (SpringModelSearchers#findBeans) that are used to provide further context for the completion. This could be a great improvement later on, when using it in a Spring project.

@PhilKes
Copy link
Contributor Author

PhilKes commented May 20, 2024

image
The JetBrains IDEs also offer a neat little tool PSI Viewer(Tools -> View PSI Structure of Current File) to view the PSI tree of a file, which could be very helpful in extracting the correct PsiElements during development.

@carlrobertoh
Copy link
Owner

This is really awesome work and one of the missing pieces of CodeGPT! 🚀 💯

Few comments:

Note: I disabled the code-completion from being stopped at "\n" for this test, but didn't increase the maxTokens

Hmm, cancelling the request at '\n' was removed in the latest release. Also, maxTokens are calculated dynamically instead of letting the user decide. The current solution is somewhat funky, but it works quite well in some situations.

In theory we could also add library source code to the prompt since they can be evaluated with PSI as well. Since models are only trained on specific timestamps, this could be used to "keep them up-to-date" with newer library source code

Yes, and I think we should already include this change in the current branch. This shouldn't require any additional implementation IF you remove the PsiTarget -> VirtualFile mapping and take the content directly from the PSI element.

Prompts have much more tokens (e.g. 131 without context vs 2024 with context), therefore also higher response times

This is inevitable, we just need to find the perfect balance.

Which model is the best compromise between response time and completion quality?

Currently, most users are using the OpenAI provider, which means that gpt-3.5-turbo-instruct should be considered the primary model for code completions.

Should the user have an option to include/exclude this automatic context for code-completions?

I think so, similarily to how we allow users to enable/disable completion post-processing. Eventually, we can remove them altogether, as they can be relatively hard for users to understand.

} else {
infillDetails.context.contextFiles.map {
"<|file_separator|>${it.path} \n" +
it.readText()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, this will result in too many input tokens. Instead of sending the entire file, could we send the actual PSI references that were obtained previously?

class InfillContext(val repoName: String, val file: VirtualFile, val psiElements: Set<PsiElement>)

and then

infillDetails.context.psiElements.map { "#${it.containingFile.virtualFile.path}\n" + it.text }

Of course, some additional filtering or mapping is required for PsiClass types, as they may contain irrelevant context if passed along directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to if e.g. there is a method call to StringUtils.capitalize that only the source code of the method should be included, not its entire class?
Yes that would be possible, although I am not sure if the models will get confused by that, because from what I read during training they always provided the entire source code file, not just "relevant" parts (for the models with repository-level completion tokens). But I would also prefer just to send the relevant parts obviously.

Copy link
Contributor Author

@PhilKes PhilKes May 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a method ClsMethodImpl.sourceMirrorMethod which seems to return the source code of the method as a PsiElement. If you did not yet use the "Download sources" action it returns null, but if you did it return this, e.g. for StringUtils.capitalize:

ClsMethodImpl.sourceMirrorMethod.text
/**
   * <p>Capitalizes a String changing the first character to title case as
   * per {@link Character#toTitleCase(int)}. No other characters are changed.</p>
   *
   * <p>For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}.
   * A {@code null} input String returns {@code null}.</p>
   *
   * <pre>
   * StringUtils.capitalize(null)  = null
   * StringUtils.capitalize("")    = ""
   * StringUtils.capitalize("cat") = "Cat"
   * StringUtils.capitalize("cAt") = "CAt"
   * StringUtils.capitalize("'cat'") = "'cat'"
   * </pre>
   *
   * @param str the String to capitalize, may be null
   * @return the capitalized String, {@code null} if null String input
   * @see org.apache.commons.lang3.text.WordUtils#capitalize(String)
   * @see #uncapitalize(String)
   * @since 2.0
   */
  public static String capitalize(final String str) {
      final int strLen = length(str);
      if (strLen == 0) {
          return str;
      }

      final int firstCodepoint = str.codePointAt(0);
      final int newCodePoint = Character.toTitleCase(firstCodepoint);
      if (firstCodepoint == newCodePoint) {
          // already capitalized
          return str;
      }

      final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
      int outOffset = 0;
      newCodePoints[outOffset++] = newCodePoint; // copy the first codepoint
      for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
          final int codepoint = str.codePointAt(inOffset);
          newCodePoints[outOffset++] = codepoint; // copy the remaining ones
          inOffset += Character.charCount(codepoint);
       }
      return new String(newCodePoints, 0, outOffset);
  }

Internally the sourceMirrorMethod uses ClsClassImpl.getSourceMirrorClass

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean to if e.g. there is a method call to StringUtils.capitalize that only the source code of the method should be included, not its entire class?

Exactly!

Yes that would be possible, although I am not sure if the models will get confused by that, because from what I read during training they always provided the entire source code file, not just "relevant" parts (for the models with repository-level completion tokens). But I would also prefer just to send the relevant parts obviously.

I tried sending snippets of code before the prefix of a cursor, and gpt-3.5-instruct didn't seem to struggle with it, given that the entire context was syntactically incorrect. However, it may be different per model.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I guess we can try out some simple template like:

# file_x.py:
<code snippet>

# file_y.py:
<code snippet>

# file_z.py:
<|fim_prefix|> ${infillDetails.prefix} <|fim_suffix|>${infillDetails.suffix} <|fim_middle|>

Hopefully at some point there will be a successor of the gpt-3.5-instruct model with better support for multi-level completions

Copy link
Contributor Author

@PhilKes PhilKes May 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed some changes. Now only the code snippets of the PsiTarget are added to the prompt. I also added that no JDK internal references are added to the prompt. Also I might have been wrong about that the source code of libraries have to be present to get useful "source" snippets. If I read the text of the navigationElement and the source is not downloaded yet, the IntelliJ SDK returns the decompiled code, which obviously is as good as the real source code, but for example if I have the following scenario:

//imports...
@Service
public class MovieUtils {

    private final MovieService movieService;

    public MovieUtils(MovieService movieService) {
        this.movieService = movieService;
    }

    public List<Movie> getMoviesSortedByPlaytime(String name) {
        var o = new ObjectMapper();
        return IntStream.range(0,10)  
    }
}

The prompt looks like this:

Infillprompt (CodeQwen, Jackson library sources not downloaded)
<reponame>movieland-backend
<file_sep>/home/user/IdeaProjects/MovieLand/movieland-backend/src/main/java/com/phil/movieland/rest/service/MovieService.java 
/**
 * Service to interface movieRepository + TmdbApi
 */
@Service
public class MovieService {

    private final MovieRepository movieRepository;
    private final TmdbApiService tmdbApiService;

    private Logger log = LoggerFactory.getLogger(MovieService.class);

    @Autowired
    public MovieService(MovieRepository movieRepository, TmdbApiService tmdbApiService) {
        this.movieRepository = movieRepository;
        this.tmdbApiService = tmdbApiService;
    }

    public List<Movie> getAllMovies() {
        List<Movie> movies = movieRepository.findAllByOrderByName();
        return loadTmdbMovies(movies);
    }

    public Slice<Movie> getAllMoviesPaged(int page, int size) {
        Slice<Movie> movies = movieRepository.findAllByOrderByName(PageRequest.of(page, size));
        loadTmdbMovies(movies.getContent());
        return movies;
    }

    public List<Movie> queryAllMovies(String queryName) {
        log.info("Querying Movies for '{}'", queryName);
        List<Movie> movies = movieRepository.findAllByNameContainsOrderByName(queryName);
        return loadTmdbMovies(movies);
    }

    public Slice<Movie> queryAllMoviesPaged(String queryName, int page, int size) {
        log.info("Querying Movies for '{}', page {}, size {}", queryName, page, size);
        Slice<Movie> movies = movieRepository.findAllByNameContainsOrderByName(queryName, PageRequest.of(page, size));
        loadTmdbMovies(movies.getContent());
        return movies;
    }

    public Optional<Movie> queryMovie(long movieId) {
        log.info("Fetching Movie by id '{}'", movieId);
        Optional<Movie> movie = movieRepository.findById(movieId);
        movie.ifPresent(value -> setTmdbData(value, true));
        return movie;
    }

    public List<Movie> queryTmdbMovies(String name) {
        return tmdbApiService.getMoviesFromTmdb(name).stream().map(tmdbMovie -> {
            Movie mov = new Movie();
            mov.setTmdbMovie(tmdbMovie);
            return mov;
        }).collect(Collectors.toList());
    }

    public List<Movie> queryTmdbTop10Movies() {
        return tmdbApiService.getTop10Movies().stream().map(tmdbMovie -> {
            Movie mov = new Movie();
            mov.setTmdbMovie(tmdbMovie);
            return mov;
        }).collect(Collectors.toList());
    }

    public Movie saveMovieIfNotExists(Movie movie) throws Exception {
        if (movie.getTmdbId() == null) {
            setTmdbData(movie, false);
        }
        Optional<Movie> duplicate = movieRepository.findFirstByTmdbId(movie.getTmdbId());
        if (duplicate.isPresent()) {
            if (duplicate.get().getMovId() != movie.getMovId()) {
                log.warn("Movie '{}' already exists!", movie.getName());
                throw new Exception(movie.getName() + " is already in the Database!");
            }
        }
        log.info("Saving Movie: '{}' ", movie.getName());
        return movieRepository.save(movie);
    }

    public void deleteById(long movieId) {
        log.info("Deleting Movie by id: '{}'", movieId);
        movieRepository.deleteById(movieId);
    }

    private void updateMovie(Movie movie) {
        log.info("Updating Movie '{}'", movie.getName());
        movieRepository.save(movie);
    }

    /**
     * Load infos from TMDB and set in movies
     */
    private List<Movie> loadTmdbMovies(List<Movie> movies) {
        for (Movie movie : movies) {
            setTmdbData(movie, true);
        }
        return movies;
    }

    private void setTmdbData(Movie movie, boolean update) {
        if (movie.getTmdbId() == null) {
            log.info("Updating TMDB data for movie '{}'", movie.getName());
            movie.setTmdbMovie(tmdbApiService.getMovieFromTmdb(movie));
            if (update) {
                updateMovie(movie);
            }
        }

    }

    public String getBackdrop(Long movId) {
        return tmdbApiService.getBackdrop(movId);
    }

    public Optional<String> getTrailer(Long movId) {
        Optional<Movie> movie = movieRepository.findById(movId);
        if (movie.isEmpty()) {
            return Optional.empty();
        }
        return Optional.of(tmdbApiService.getTrailerURL(movie.get().getTmdbId()));
    }

    public List<Movie> queryMoviesByIds(List<Long> movIds) {
        log.info("Fetching Movies by ids '{}'", Utils.joinToStringList(movIds));
        return movieRepository.findAllByMovIdIn(movIds);
    }

    public void deleteAll() {
        log.info("Deleting all Movies");
        movieRepository.deleteAll();
    }
}
<file_sep>/home/user/IdeaProjects/MovieLand/movieland-backend/src/main/java/com/phil/movieland/data/entity/Movie.java 
@Entity
@Table(name="MOVIE")
public class Movie {

    @Id
    @Column(name="MOVIE_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long movId;

    @Column(name="NAME")
    private String name;

    @Column(name="RELEASE_DATE")
    @Temporal(TemporalType.DATE)
    private Date date;

    @Column(name="DESCRIPTION")
    private String description;

    @Column(name="POSTER_URL", nullable=true)
    private String posterUrl;

    @Column(name="LENGTH", nullable=true)
    private Long length;

    @Column(name="TMDB_ID")
    private Long tmdbId;

    //Additional info, actors,... from TMDB
    @Transient //Ignore for Persistence in Database
    @JsonIgnore
    private MovieDb tmdbMovie;

    public Movie() {
    }

    public Movie(long movId, String name, Date date, String description) {
        this.movId = movId;
        this.name = name;
        this.date = date;
        this.description = description;
    }

    public Long getLength() {
        return length;
    }

    public void setLength(Long length) {
        this.length=length;
    }

    public void setTmdbId(Long tmdbId) {
        this.tmdbId=tmdbId;
    }

    public long getMovId() {
        return movId;
    }

    public void setMovId(long movId) {
        this.movId=movId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name=name;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date=date;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description=description;
    }

    public Long getTmdbId() {
        return tmdbId;
    }

    public String getPosterUrl() {
        return posterUrl;
    }

    public void setPosterUrl(String posterUrl) {
        this.posterUrl=posterUrl;
    }

    public MovieDb getTmdbMovie() {
        return tmdbMovie;
    }

    public void setTmdbMovie(MovieDb tmdbMovie) {
        this.tmdbMovie=tmdbMovie;
        this.tmdbId=(long) tmdbMovie.getId();
        this.posterUrl=TmdbApiService.POSTER_BASE_URL + tmdbMovie.getPosterPath();
        this.length=(long) tmdbMovie.getRuntime();

        this.description=tmdbMovie.getOverview();
        if(description.length()>255) {
            description=description.substring(0, 252) + "...";
        }
        if(tmdbMovie.getReleaseDate()!=null && !tmdbMovie.getReleaseDate().isEmpty()) {
            this.date=DateUtils.createDateFromDateString(tmdbMovie.getReleaseDate());
        }
        this.name=tmdbMovie.getTitle();
    }
}
<file_sep>/home/user/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.14.1/jackson-databind-2.14.1.jar!/com/fasterxml/jackson/databind/ObjectMapper.class 
public class ObjectMapper extends ObjectCodec implements Versioned, Serializable {
    private static final long serialVersionUID = 2L;
    protected static final AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector();
    protected static final BaseSettings DEFAULT_BASE;
    protected final JsonFactory _jsonFactory;
    protected TypeFactory _typeFactory;
    protected InjectableValues _injectableValues;
    protected SubtypeResolver _subtypeResolver;
    protected final ConfigOverrides _configOverrides;
    protected final CoercionConfigs _coercionConfigs;
    protected SimpleMixInResolver _mixIns;
    protected SerializationConfig _serializationConfig;
    protected DefaultSerializerProvider _serializerProvider;
    protected SerializerFactory _serializerFactory;
    protected DeserializationConfig _deserializationConfig;
    protected DefaultDeserializationContext _deserializationContext;
    protected Set<Object> _registeredModuleTypes;
    protected final ConcurrentHashMap<JavaType, JsonDeserializer<Object>> _rootDeserializers;

    public ObjectMapper() {
        this((JsonFactory)null, (DefaultSerializerProvider)null, (DefaultDeserializationContext)null);
    }

    public ObjectMapper(JsonFactory jf) {
        this(jf, (DefaultSerializerProvider)null, (DefaultDeserializationContext)null);
    }

    protected ObjectMapper(ObjectMapper src) {
        this(src, (JsonFactory)null);
    }

    protected ObjectMapper(ObjectMapper src, JsonFactory factory) {
        this._rootDeserializers = new ConcurrentHashMap(64, 0.6F, 2);
        this._jsonFactory = factory != null ? factory : src._jsonFactory.copy();
        this._jsonFactory.setCodec(this);
        this._subtypeResolver = src._subtypeResolver.copy();
        this._typeFactory = src._typeFactory;
        this._injectableValues = src._injectableValues;
        this._configOverrides = src._configOverrides.copy();
        this._coercionConfigs = src._coercionConfigs.copy();
        this._mixIns = src._mixIns.copy();
        RootNameLookup rootNames = new RootNameLookup();
        this._serializationConfig = new SerializationConfig(src._serializationConfig, this._subtypeResolver, this._mixIns, rootNames, this._configOverrides);
        this._deserializationConfig = new DeserializationConfig(src._deserializationConfig, this._subtypeResolver, this._mixIns, rootNames, this._configOverrides, this._coercionConfigs);
        this._serializerProvider = src._serializerProvider.copy();
        this._deserializationContext = src._deserializationContext.copy();
        this._serializerFactory = src._serializerFactory;
        Set<Object> reg = src._registeredModuleTypes;
        if (reg == null) {
            this._registeredModuleTypes = null;
        } else {
            this._registeredModuleTypes = new LinkedHashSet(reg);
        }

    }

    public ObjectMapper(JsonFactory jf, DefaultSerializerProvider sp, DefaultDeserializationContext dc) {
        this._rootDeserializers = new ConcurrentHashMap(64, 0.6F, 2);
        if (jf == null) {
            this._jsonFactory = new MappingJsonFactory(this);
        } else {
            this._jsonFactory = jf;
            if (jf.getCodec() == null) {
                this._jsonFactory.setCodec(this);
            }
        }

        this._subtypeResolver = new StdSubtypeResolver();
        RootNameLookup rootNames = new RootNameLookup();
        this._typeFactory = TypeFactory.defaultInstance();
        SimpleMixInResolver mixins = new SimpleMixInResolver((ClassIntrospector.MixInResolver)null);
        this._mixIns = mixins;
        BaseSettings base = DEFAULT_BASE.withClassIntrospector(this.defaultClassIntrospector());
        this._configOverrides = new ConfigOverrides();
        this._coercionConfigs = new CoercionConfigs();
        this._serializationConfig = new SerializationConfig(base, this._subtypeResolver, mixins, rootNames, this._configOverrides, DatatypeFeatures.defaultFeatures());
        this._deserializationConfig = new DeserializationConfig(base, this._subtypeResolver, mixins, rootNames, this._configOverrides, this._coercionConfigs, DatatypeFeatures.defaultFeatures());
        boolean needOrder = this._jsonFactory.requiresPropertyOrdering();
        if (needOrder ^ this._serializationConfig.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)) {
            this.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, needOrder);
        }

        this._serializerProvider = (DefaultSerializerProvider)(sp == null ? new DefaultSerializerProvider.Impl() : sp);
        this._deserializationContext = (DefaultDeserializationContext)(dc == null ? new DefaultDeserializationContext.Impl(BeanDeserializerFactory.instance) : dc);
        this._serializerFactory = BeanSerializerFactory.instance;
    }

    protected ClassIntrospector defaultClassIntrospector() {
        return new BasicClassIntrospector();
    }

    public ObjectMapper copy() {
        this._checkInvalidCopy(ObjectMapper.class);
        return new ObjectMapper(this);
    }

    public ObjectMapper copyWith(JsonFactory factory) {
        this._checkInvalidCopy(ObjectMapper.class);
        return new ObjectMapper(this, factory);
    }

    protected void _checkInvalidCopy(Class<?> exp) {
        if (this.getClass() != exp) {
            throw new IllegalStateException("Failed copy()/copyWith(): " + this.getClass().getName() + " (version: " + this.version() + ") does not override copy()/copyWith(); it has to");
        }
    }

    protected ObjectReader _newReader(DeserializationConfig config) {
        return new ObjectReader(this, config);
    }

    protected ObjectReader _newReader(DeserializationConfig config, JavaType valueType, Object valueToUpdate, FormatSchema schema, InjectableValues injectableValues) {
        return new ObjectReader(this, config, valueType, valueToUpdate, schema, injectableValues);
    }

    protected ObjectWriter _newWriter(SerializationConfig config) {
        return new ObjectWriter(this, config);
    }

    protected ObjectWriter _newWriter(SerializationConfig config, FormatSchema schema) {
        return new ObjectWriter(this, config, schema);
    }

    protected ObjectWriter _newWriter(SerializationConfig config, JavaType rootType, PrettyPrinter pp) {
        return new ObjectWriter(this, config, rootType, pp);
    }

    public Version version() {
        return PackageVersion.VERSION;
    }

    public ObjectMapper registerModule(Module module) {
        this._assertNotNull("module", module);
        String name = module.getModuleName();
        if (name == null) {
            throw new IllegalArgumentException("Module without defined name");
        } else {
            Version version = module.version();
            if (version == null) {
                throw new IllegalArgumentException("Module without defined version");
            } else {
                Iterator var4 = module.getDependencies().iterator();

                while(var4.hasNext()) {
                    Module dep = (Module)var4.next();
                    this.registerModule(dep);
                }

                if (this.isEnabled(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS)) {
                    Object typeId = module.getTypeId();
                    if (typeId != null) {
                        if (this._registeredModuleTypes == null) {
                            this._registeredModuleTypes = new LinkedHashSet();
                        }

                        if (!this._registeredModuleTypes.add(typeId)) {
                            return this;
                        }
                    }
                }

                module.setupModule(new Module.SetupContext() {
                    public Version getMapperVersion() {
                        return ObjectMapper.this.version();
                    }

                    public <C extends ObjectCodec> C getOwner() {
                        return ObjectMapper.this;
                    }

                    public TypeFactory getTypeFactory() {
                        return ObjectMapper.this._typeFactory;
                    }

                    public boolean isEnabled(MapperFeature f) {
                        return ObjectMapper.this.isEnabled(f);
                    }

                    public boolean isEnabled(DeserializationFeature f) {
                        return ObjectMapper.this.isEnabled(f);
                    }

                    public boolean isEnabled(SerializationFeature f) {
                        return ObjectMapper.this.isEnabled(f);
                    }

                    public boolean isEnabled(JsonFactory.Feature f) {
                        return ObjectMapper.this.isEnabled(f);
                    }

                    public boolean isEnabled(JsonParser.Feature f) {
                        return ObjectMapper.this.isEnabled(f);
                    }

                    public boolean isEnabled(JsonGenerator.Feature f) {
                        return ObjectMapper.this.isEnabled(f);
                    }

                    public MutableConfigOverride configOverride(Class<?> type) {
                        return ObjectMapper.this.configOverride(type);
                    }

                    public void addDeserializers(Deserializers d) {
                        DeserializerFactory df = ObjectMapper.this._deserializationContext._factory.withAdditionalDeserializers(d);
                        ObjectMapper.this._deserializationContext = ObjectMapper.this._deserializationContext.with(df);
                    }

                    public void addKeyDeserializers(KeyDeserializers d) {
                        DeserializerFactory df = ObjectMapper.this._deserializationContext._factory.withAdditionalKeyDeserializers(d);
                        ObjectMapper.this._deserializationContext = ObjectMapper.this._deserializationContext.with(df);
                    }

                    public void addBeanDeserializerModifier(BeanDeserializerModifier modifier) {
                        DeserializerFactory df = ObjectMapper.this._deserializationContext._factory.withDeserializerModifier(modifier);
                        ObjectMapper.this._deserializationContext = ObjectMapper.this._deserializationContext.with(df);
                    }

                    public void addSerializers(Serializers s) {
                        ObjectMapper.this._serializerFactory = ObjectMapper.this._serializerFactory.withAdditionalSerializers(s);
                    }

                    public void addKeySerializers(Serializers s) {
                        ObjectMapper.this._serializerFactory = ObjectMapper.this._serializerFactory.withAdditionalKeySerializers(s);
                    }

                    public void addBeanSerializerModifier(BeanSerializerModifier modifier) {
                        ObjectMapper.this._serializerFactory = ObjectMapper.this._serializerFactory.withSerializerModifier(modifier);
                    }

                    public void addAbstractTypeResolver(AbstractTypeResolver resolver) {
                        DeserializerFactory df = ObjectMapper.this._deserializationContext._factory.withAbstractTypeResolver(resolver);
                        ObjectMapper.this._deserializationContext = ObjectMapper.this._deserializationContext.with(df);
                    }

                    public void addTypeModifier(TypeModifier modifier) {
                        TypeFactory f = ObjectMapper.this._typeFactory;
                        f = f.withModifier(modifier);
                        ObjectMapper.this.setTypeFactory(f);
                    }

                    public void addValueInstantiators(ValueInstantiators instantiators) {
                        DeserializerFactory df = ObjectMapper.this._deserializationContext._factory.withValueInstantiators(instantiators);
                        ObjectMapper.this._deserializationContext = ObjectMapper.this._deserializationContext.with(df);
                    }

                    public void setClassIntrospector(ClassIntrospector ci) {
                        ObjectMapper.this._deserializationConfig = (DeserializationConfig)ObjectMapper.this._deserializationConfig.with(ci);
                        ObjectMapper.this._serializationConfig = (SerializationConfig)ObjectMapper.this._serializationConfig.with(ci);
                    }

                    public void insertAnnotationIntrospector(AnnotationIntrospector ai) {
                        ObjectMapper.this._deserializationConfig = (DeserializationConfig)ObjectMapper.this._deserializationConfig.withInsertedAnnotationIntrospector(ai);
                        ObjectMapper.this._serializationConfig = (SerializationConfig)ObjectMapper.this._serializationConfig.withInsertedAnnotationIntrospector(ai);
                    }

                    public void appendAnnotationIntrospector(AnnotationIntrospector ai) {
                        ObjectMapper.this._deserializationConfig = (DeserializationConfig)ObjectMapper.this._deserializationConfig.withAppendedAnnotationIntrospector(ai);
                        ObjectMapper.this._serializationConfig = (SerializationConfig)ObjectMapper.this._serializationConfig.withAppendedAnnotationIntrospector(ai);
                    }

                    public void registerSubtypes(Class<?>... subtypes) {
                        ObjectMapper.this.registerSubtypes(subtypes);
                    }

                    public void registerSubtypes(NamedType... subtypes) {
                        ObjectMapper.this.registerSubtypes(subtypes);
                    }

                    public void registerSubtypes(Collection<Class<?>> subtypes) {
                        ObjectMapper.this.registerSubtypes(subtypes);
                    }

                    public void setMixInAnnotations(Class<?> target, Class<?> mixinSource) {
                        ObjectMapper.this.addMixIn(target, mixinSource);
                    }

                    public void addDeserializationProblemHandler(DeserializationProblemHandler handler) {
                        ObjectMapper.this.addHandler(handler);
                    }

                    public void setNamingStrategy(PropertyNamingStrategy naming) {
                        ObjectMapper.this.setPropertyNamingStrategy(naming);
                    }
                });
                return this;
            }
        }
    }

    public ObjectMapper registerModules(Module... modules) {
        Module[] var2 = modules;
        int var3 = modules.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            Module module = var2[var4];
            this.registerModule(module);
        }

        return this;
    }

    public ObjectMapper registerModules(Iterable<? extends Module> modules) {
        this._assertNotNull("modules", modules);
        Iterator var2 = modules.iterator();

        while(var2.hasNext()) {
            Module module = (Module)var2.next();
            this.registerModule(module);
        }

        return this;
    }

    public Set<Object> getRegisteredModuleIds() {
        return this._registeredModuleTypes == null ? Collections.emptySet() : Collections.unmodifiableSet(this._registeredModuleTypes);
    }

    public static List<Module> findModules() {
        return findModules((ClassLoader)null);
    }

    public static List<Module> findModules(ClassLoader classLoader) {
        ArrayList<Module> modules = new ArrayList();
        ServiceLoader<Module> loader = secureGetServiceLoader(Module.class, classLoader);
        Iterator var3 = loader.iterator();

        while(var3.hasNext()) {
            Module module = (Module)var3.next();
            modules.add(module);
        }

        return modules;
    }

    private static <T> ServiceLoader<T> secureGetServiceLoader(final Class<T> clazz, final ClassLoader classLoader) {
        SecurityManager sm = System.getSecurityManager();
        if (sm == null) {
            return classLoader == null ? ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
        } else {
            return (ServiceLoader)AccessController.doPrivileged(new PrivilegedAction<ServiceLoader<T>>() {
                public ServiceLoader<T> run() {
                    return classLoader == null ? ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
                }
            });
        }
    }

    public ObjectMapper findAndRegisterModules() {
        return this.registerModules((Iterable)findModules());
    }

    public JsonGenerator createGenerator(OutputStream out) throws IOException {
        this._assertNotNull("out", out);
        JsonGenerator g = this._jsonFactory.createGenerator(out, JsonEncoding.UTF8);
        this._serializationConfig.initialize(g);
        return g;
    }

    public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException {
        this._assertNotNull("out", out);
        JsonGenerator g = this._jsonFactory.createGenerator(out, enc);
        this._serializationConfig.initialize(g);
        return g;
    }

    public JsonGenerator createGenerator(Writer w) throws IOException {
        this._assertNotNull("w", w);
        JsonGenerator g = this._jsonFactory.createGenerator(w);
        this._serializationConfig.initialize(g);
        return g;
    }

    public JsonGenerator createGenerator(File outputFile, JsonEncoding enc) throws IOException {
        this._assertNotNull("outputFile", outputFile);
        JsonGenerator g = this._jsonFactory.createGenerator(outputFile, enc);
        this._serializationConfig.initialize(g);
        return g;
    }

    public JsonGenerator createGenerator(DataOutput out) throws IOException {
        this._assertNotNull("out", out);
        JsonGenerator g = this._jsonFactory.createGenerator(out);
        this._serializationConfig.initialize(g);
        return g;
    }

    public JsonParser createParser(File src) throws IOException {
        this._assertNotNull("src", src);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(src));
    }

    public JsonParser createParser(URL src) throws IOException {
        this._assertNotNull("src", src);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(src));
    }

    public JsonParser createParser(InputStream in) throws IOException {
        this._assertNotNull("in", in);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(in));
    }

    public JsonParser createParser(Reader r) throws IOException {
        this._assertNotNull("r", r);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(r));
    }

    public JsonParser createParser(byte[] content) throws IOException {
        this._assertNotNull("content", content);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(content));
    }

    public JsonParser createParser(byte[] content, int offset, int len) throws IOException {
        this._assertNotNull("content", content);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(content, offset, len));
    }

    public JsonParser createParser(String content) throws IOException {
        this._assertNotNull("content", content);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(content));
    }

    public JsonParser createParser(char[] content) throws IOException {
        this._assertNotNull("content", content);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(content));
    }

    public JsonParser createParser(char[] content, int offset, int len) throws IOException {
        this._assertNotNull("content", content);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(content, offset, len));
    }

    public JsonParser createParser(DataInput content) throws IOException {
        this._assertNotNull("content", content);
        return this._deserializationConfig.initialize(this._jsonFactory.createParser(content));
    }

    public JsonParser createNonBlockingByteArrayParser() throws IOException {
        return this._deserializationConfig.initialize(this._jsonFactory.createNonBlockingByteArrayParser());
    }

    public SerializationConfig getSerializationConfig() {
        return this._serializationConfig;
    }

    public DeserializationConfig getDeserializationConfig() {
        return this._deserializationConfig;
    }

    public DeserializationContext getDeserializationContext() {
        return this._deserializationContext;
    }

    public ObjectMapper setSerializerFactory(SerializerFactory f) {
        this._serializerFactory = f;
        return this;
    }

    public SerializerFactory getSerializerFactory() {
        return this._serializerFactory;
    }

    public ObjectMapper setSerializerProvider(DefaultSerializerProvider p) {
        this._serializerProvider = p;
        return this;
    }

    public SerializerProvider getSerializerProvider() {
        return this._serializerProvider;
    }

    public SerializerProvider getSerializerProviderInstance() {
        return this._serializerProvider(this._serializationConfig);
    }

    public ObjectMapper setMixIns(Map<Class<?>, Class<?>> sourceMixins) {
        this._mixIns.setLocalDefinitions(sourceMixins);
        return this;
    }

    public ObjectMapper addMixIn(Class<?> target, Class<?> mixinSource) {
        this._mixIns.addLocalDefinition(target, mixinSource);
        return this;
    }

    public ObjectMapper setMixInResolver(ClassIntrospector.MixInResolver resolver) {
        SimpleMixInResolver r = this._mixIns.withOverrides(resolver);
        if (r != this._mixIns) {
            this._mixIns = r;
            this._deserializationConfig = new DeserializationConfig(this._deserializationConfig, r);
            this._serializationConfig = new SerializationConfig(this._serializationConfig, r);
        }

        return this;
    }

    public Class<?> findMixInClassFor(Class<?> cls) {
        return this._mixIns.findMixInClassFor(cls);
    }

    public int mixInCount() {
        return this._mixIns.localSize();
    }

    /** @deprecated */
    @Deprecated
    public void setMixInAnnotations(Map<Class<?>, Class<?>> sourceMixins) {
        this.setMixIns(sourceMixins);
    }

    /** @deprecated */
    @Deprecated
    public final void addMixInAnnotations(Class<?> target, Class<?> mixinSource) {
        this.addMixIn(target, mixinSource);
    }

    public VisibilityChecker<?> getVisibilityChecker() {
        return this._serializationConfig.getDefaultVisibilityChecker();
    }

    public ObjectMapper setVisibility(VisibilityChecker<?> vc) {
        this._configOverrides.setDefaultVisibility(vc);
        return this;
    }

    public ObjectMapper setVisibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) {
        VisibilityChecker<?> vc = this._configOverrides.getDefaultVisibility();
        vc = vc.withVisibility(forMethod, visibility);
        this._configOverrides.setDefaultVisibility(vc);
        return this;
    }

    public SubtypeResolver getSubtypeResolver() {
        return this._subtypeResolver;
    }

    public ObjectMapper setSubtypeResolver(SubtypeResolver str) {
        this._subtypeResolver = str;
        this._deserializationConfig = this._deserializationConfig.with(str);
        this._serializationConfig = this._serializationConfig.with(str);
        return this;
    }

    public ObjectMapper setAnnotationIntrospector(AnnotationIntrospector ai) {
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(ai);
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(ai);
        return this;
    }

    public ObjectMapper setAnnotationIntrospectors(AnnotationIntrospector serializerAI, AnnotationIntrospector deserializerAI) {
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(serializerAI);
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(deserializerAI);
        return this;
    }

    public ObjectMapper setPropertyNamingStrategy(PropertyNamingStrategy s) {
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(s);
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(s);
        return this;
    }

    public PropertyNamingStrategy getPropertyNamingStrategy() {
        return this._serializationConfig.getPropertyNamingStrategy();
    }

    public ObjectMapper setAccessorNaming(AccessorNamingStrategy.Provider s) {
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(s);
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(s);
        return this;
    }

    public ObjectMapper setDefaultPrettyPrinter(PrettyPrinter pp) {
        this._serializationConfig = this._serializationConfig.withDefaultPrettyPrinter(pp);
        return this;
    }

    /** @deprecated */
    @Deprecated
    public void setVisibilityChecker(VisibilityChecker<?> vc) {
        this.setVisibility(vc);
    }

    public ObjectMapper setPolymorphicTypeValidator(PolymorphicTypeValidator ptv) {
        BaseSettings s = this._deserializationConfig.getBaseSettings().with(ptv);
        this._deserializationConfig = this._deserializationConfig._withBase(s);
        return this;
    }

    public PolymorphicTypeValidator getPolymorphicTypeValidator() {
        return this._deserializationConfig.getBaseSettings().getPolymorphicTypeValidator();
    }

    public ObjectMapper setSerializationInclusion(JsonInclude.Include incl) {
        this.setPropertyInclusion(Value.construct(incl, incl));
        return this;
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper setPropertyInclusion(JsonInclude.Value incl) {
        return this.setDefaultPropertyInclusion(incl);
    }

    public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Value incl) {
        this._configOverrides.setDefaultInclusion(incl);
        return this;
    }

    public ObjectMapper setDefaultPropertyInclusion(JsonInclude.Include incl) {
        this._configOverrides.setDefaultInclusion(Value.construct(incl, incl));
        return this;
    }

    public ObjectMapper setDefaultSetterInfo(JsonSetter.Value v) {
        this._configOverrides.setDefaultSetterInfo(v);
        return this;
    }

    public ObjectMapper setDefaultVisibility(JsonAutoDetect.Value vis) {
        this._configOverrides.setDefaultVisibility(Std.construct(vis));
        return this;
    }

    public ObjectMapper setDefaultMergeable(Boolean b) {
        this._configOverrides.setDefaultMergeable(b);
        return this;
    }

    public ObjectMapper setDefaultLeniency(Boolean b) {
        this._configOverrides.setDefaultLeniency(b);
        return this;
    }

    public void registerSubtypes(Class<?>... classes) {
        this.getSubtypeResolver().registerSubtypes(classes);
    }

    public void registerSubtypes(NamedType... types) {
        this.getSubtypeResolver().registerSubtypes(types);
    }

    public void registerSubtypes(Collection<Class<?>> subtypes) {
        this.getSubtypeResolver().registerSubtypes(subtypes);
    }

    public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv) {
        return this.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);
    }

    public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv, DefaultTyping applicability) {
        return this.activateDefaultTyping(ptv, applicability, As.WRAPPER_ARRAY);
    }

    public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv, DefaultTyping applicability, JsonTypeInfo.As includeAs) {
        if (includeAs == As.EXTERNAL_PROPERTY) {
            throw new IllegalArgumentException("Cannot use includeAs of " + includeAs);
        } else {
            TypeResolverBuilder<?> typer = this._constructDefaultTypeResolverBuilder(applicability, ptv);
            typer = typer.init(Id.CLASS, (TypeIdResolver)null);
            typer = typer.inclusion(includeAs);
            return this.setDefaultTyping(typer);
        }
    }

    public ObjectMapper activateDefaultTypingAsProperty(PolymorphicTypeValidator ptv, DefaultTyping applicability, String propertyName) {
        TypeResolverBuilder<?> typer = this._constructDefaultTypeResolverBuilder(applicability, ptv);
        typer = typer.init(Id.CLASS, (TypeIdResolver)null);
        typer = typer.inclusion(As.PROPERTY);
        typer = typer.typeProperty(propertyName);
        return this.setDefaultTyping(typer);
    }

    public ObjectMapper deactivateDefaultTyping() {
        return this.setDefaultTyping((TypeResolverBuilder)null);
    }

    public ObjectMapper setDefaultTyping(TypeResolverBuilder<?> typer) {
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(typer);
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(typer);
        return this;
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper enableDefaultTyping() {
        return this.activateDefaultTyping(this.getPolymorphicTypeValidator());
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper enableDefaultTyping(DefaultTyping dti) {
        return this.enableDefaultTyping(dti, As.WRAPPER_ARRAY);
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs) {
        return this.activateDefaultTyping(this.getPolymorphicTypeValidator(), applicability, includeAs);
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper enableDefaultTypingAsProperty(DefaultTyping applicability, String propertyName) {
        return this.activateDefaultTypingAsProperty(this.getPolymorphicTypeValidator(), applicability, propertyName);
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper disableDefaultTyping() {
        return this.setDefaultTyping((TypeResolverBuilder)null);
    }

    public MutableConfigOverride configOverride(Class<?> type) {
        return this._configOverrides.findOrCreateOverride(type);
    }

    public MutableCoercionConfig coercionConfigDefaults() {
        return this._coercionConfigs.defaultCoercions();
    }

    public MutableCoercionConfig coercionConfigFor(LogicalType logicalType) {
        return this._coercionConfigs.findOrCreateCoercion(logicalType);
    }

    public MutableCoercionConfig coercionConfigFor(Class<?> physicalType) {
        return this._coercionConfigs.findOrCreateCoercion(physicalType);
    }

    public TypeFactory getTypeFactory() {
        return this._typeFactory;
    }

    public ObjectMapper setTypeFactory(TypeFactory f) {
        this._typeFactory = f;
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(f);
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(f);
        return this;
    }

    public JavaType constructType(Type t) {
        this._assertNotNull("t", t);
        return this._typeFactory.constructType(t);
    }

    public JavaType constructType(TypeReference<?> typeRef) {
        this._assertNotNull("typeRef", typeRef);
        return this._typeFactory.constructType(typeRef);
    }

    public JsonNodeFactory getNodeFactory() {
        return this._deserializationConfig.getNodeFactory();
    }

    public ObjectMapper setNodeFactory(JsonNodeFactory f) {
        this._deserializationConfig = this._deserializationConfig.with(f);
        return this;
    }

    public ObjectMapper setConstructorDetector(ConstructorDetector cd) {
        this._deserializationConfig = this._deserializationConfig.with(cd);
        return this;
    }

    public ObjectMapper addHandler(DeserializationProblemHandler h) {
        this._deserializationConfig = this._deserializationConfig.withHandler(h);
        return this;
    }

    public ObjectMapper clearProblemHandlers() {
        this._deserializationConfig = this._deserializationConfig.withNoProblemHandlers();
        return this;
    }

    public ObjectMapper setConfig(DeserializationConfig config) {
        this._assertNotNull("config", config);
        this._deserializationConfig = config;
        return this;
    }

    /** @deprecated */
    @Deprecated
    public void setFilters(FilterProvider filterProvider) {
        this._serializationConfig = this._serializationConfig.withFilters(filterProvider);
    }

    public ObjectMapper setFilterProvider(FilterProvider filterProvider) {
        this._serializationConfig = this._serializationConfig.withFilters(filterProvider);
        return this;
    }

    public ObjectMapper setBase64Variant(Base64Variant v) {
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(v);
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(v);
        return this;
    }

    public ObjectMapper setConfig(SerializationConfig config) {
        this._assertNotNull("config", config);
        this._serializationConfig = config;
        return this;
    }

    public JsonFactory tokenStreamFactory() {
        return this._jsonFactory;
    }

    public JsonFactory getFactory() {
        return this._jsonFactory;
    }

    public ObjectMapper setDateFormat(DateFormat dateFormat) {
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(dateFormat);
        this._serializationConfig = this._serializationConfig.with(dateFormat);
        return this;
    }

    public DateFormat getDateFormat() {
        return this._serializationConfig.getDateFormat();
    }

    public Object setHandlerInstantiator(HandlerInstantiator hi) {
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(hi);
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(hi);
        return this;
    }

    public ObjectMapper setInjectableValues(InjectableValues injectableValues) {
        this._injectableValues = injectableValues;
        return this;
    }

    public InjectableValues getInjectableValues() {
        return this._injectableValues;
    }

    public ObjectMapper setLocale(Locale l) {
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(l);
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(l);
        return this;
    }

    public ObjectMapper setTimeZone(TimeZone tz) {
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(tz);
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(tz);
        return this;
    }

    public ObjectMapper setDefaultAttributes(ContextAttributes attrs) {
        this._deserializationConfig = this._deserializationConfig.with(attrs);
        this._serializationConfig = this._serializationConfig.with(attrs);
        return this;
    }

    public boolean isEnabled(MapperFeature f) {
        return this._serializationConfig.isEnabled(f);
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper configure(MapperFeature f, boolean state) {
        this._serializationConfig = state ? (SerializationConfig)this._serializationConfig.with(new MapperFeature[]{f}) : (SerializationConfig)this._serializationConfig.without(new MapperFeature[]{f});
        this._deserializationConfig = state ? (DeserializationConfig)this._deserializationConfig.with(new MapperFeature[]{f}) : (DeserializationConfig)this._deserializationConfig.without(new MapperFeature[]{f});
        return this;
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper enable(MapperFeature... f) {
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(f);
        this._serializationConfig = (SerializationConfig)this._serializationConfig.with(f);
        return this;
    }

    /** @deprecated */
    @Deprecated
    public ObjectMapper disable(MapperFeature... f) {
        this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.without(f);
        this._serializationConfig = (SerializationConfig)this._serializationConfig.without(f);
        return this;
    }

    public boolean isEnabled(SerializationFeature f) {
        return this._serializationConfig.isEnabled(f);
    }

    public ObjectMapper configure(SerializationFeature f, boolean state) {
        this._serializationConfig = state ? this._serializationConfig.with(f) : this._serializationConfig.without(f);
        return this;
    }

    public ObjectMapper enable(SerializationFeature f) {
        this._serializationConfig = this._serializationConfig.with(f);
        return this;
    }

    public ObjectMapper enable(SerializationFeature first, SerializationFeature... f) {
        this._serializationConfig = this._serializationConfig.with(first, f);
        return this;
    }

    public ObjectMapper disable(SerializationFeature f) {
        this._serializationConfig = this._serializationConfig.without(f);
        return this;
    }

    public ObjectMapper disable(SerializationFeature first, SerializationFeature... f) {
        this._serializationConfig = this._serializationConfig.without(first, f);
        return this;
    }

    public boolean isEnabled(DeserializationFeature f) {
        return this._deserializationConfig.isEnabled(f);
    }

    public ObjectMapper configure(DeserializationFeature f, boolean state) {
        this._deserializationConfig = state ? this._deserializationConfig.with(f) : this._deserializationConfig.without(f);
        return this;
    }

    public ObjectMapper enable(DeserializationFeature feature) {
        this._deserializationConfig = this._deserializationConfig.with(feature);
        return this;
    }

    public ObjectMapper enable(DeserializationFeature first, DeserializationFeature... f) {
        this._deserializationConfig = this._deserializationConfig.with(first, f);
        return this;
    }

    public ObjectMapper disable(DeserializationFeature feature) {
        this._deserializationConfig = this._deserializationConfig.without(feature);
        return this;
    }

    public ObjectMapper disable(DeserializationFeature first, DeserializationFeature... f) {
        this._deserializationConfig = this._deserializationConfig.without(first, f);
        return this;
    }

    public ObjectMapper configure(DatatypeFeature f, boolean state) {
        if (state) {
            this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.with(f);
            this._serializationConfig = (SerializationConfig)this._serializationConfig.with(f);
        } else {
            this._deserializationConfig = (DeserializationConfig)this._deserializationConfig.without(f);
            this._serializationConfig = (SerializationConfig)this._serializationConfig.without(f);
        }

        return this;
    }

    public boolean isEnabled(JsonParser.Feature f) {
        return this._deserializationConfig.isEnabled(f, this._jsonFactory);
    }

    public ObjectMapper configure(JsonParser.Feature f, boolean state) {
        this._jsonFactory.configure(f, state);
        return this;
    }

    public ObjectMapper enable(JsonParser.Feature... features) {
        JsonParser.Feature[] var2 = features;
        int var3 = features.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            JsonParser.Feature f = var2[var4];
            this._jsonFactory.enable(f);
        }

        return this;
    }

    public ObjectMapper disable(JsonParser.Feature... features) {
        JsonParser.Feature[] var2 = features;
        int var3 = features.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            JsonParser.Feature f = var2[var4];
            this._jsonFactory.disable(f);
        }

        return this;
    }

    public boolean isEnabled(JsonGenerator.Feature f) {
        return this._serializationConfig.isEnabled(f, this._jsonFactory);
    }

    public ObjectMapper configure(JsonGenerator.Feature f, boolean state) {
        this._jsonFactory.configure(f, state);
        return this;
    }

    public ObjectMapper enable(JsonGenerator.Feature... features) {
        JsonGenerator.Feature[] var2 = features;
        int var3 = features.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            JsonGenerator.Feature f = var2[var4];
            this._jsonFactory.enable(f);
        }

        return this;
    }

    public ObjectMapper disable(JsonGenerator.Feature... features) {
        JsonGenerator.Feature[] var2 = features;
        int var3 = features.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            JsonGenerator.Feature f = var2[var4];
            this._jsonFactory.disable(f);
        }

        return this;
    }

    public boolean isEnabled(JsonFactory.Feature f) {
        return this._jsonFactory.isEnabled(f);
    }

    public boolean isEnabled(StreamReadFeature f) {
        return this.isEnabled(f.mappedFeature());
    }

    public boolean isEnabled(StreamWriteFeature f) {
        return this.isEnabled(f.mappedFeature());
    }

    public <T> T readValue(JsonParser p, Class<T> valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("p", p);
        return this._readValue(this.getDeserializationConfig(), p, this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("p", p);
        return this._readValue(this.getDeserializationConfig(), p, this._typeFactory.constructType(valueTypeRef));
    }

    public final <T> T readValue(JsonParser p, ResolvedType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("p", p);
        return this._readValue(this.getDeserializationConfig(), p, (JavaType)valueType);
    }

    public <T> T readValue(JsonParser p, JavaType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("p", p);
        return this._readValue(this.getDeserializationConfig(), p, valueType);
    }

    public <T extends TreeNode> T readTree(JsonParser p) throws IOException {
        this._assertNotNull("p", p);
        DeserializationConfig cfg = this.getDeserializationConfig();
        JsonToken t = p.currentToken();
        if (t == null) {
            t = p.nextToken();
            if (t == null) {
                return null;
            }
        }

        JsonNode n = (JsonNode)this._readValue(cfg, p, this.constructType((Type)JsonNode.class));
        if (n == null) {
            n = this.getNodeFactory().nullNode();
        }

        return (TreeNode)n;
    }

    public <T> MappingIterator<T> readValues(JsonParser p, ResolvedType valueType) throws IOException {
        return this.readValues(p, (JavaType)valueType);
    }

    public <T> MappingIterator<T> readValues(JsonParser p, JavaType valueType) throws IOException {
        this._assertNotNull("p", p);
        DeserializationConfig config = this.getDeserializationConfig();
        DeserializationContext ctxt = this.createDeserializationContext(p, config);
        JsonDeserializer<?> deser = this._findRootDeserializer(ctxt, valueType);
        return new MappingIterator(valueType, p, ctxt, deser, false, (Object)null);
    }

    public <T> MappingIterator<T> readValues(JsonParser p, Class<T> valueType) throws IOException {
        return this.readValues(p, this._typeFactory.constructType(valueType));
    }

    public <T> MappingIterator<T> readValues(JsonParser p, TypeReference<T> valueTypeRef) throws IOException {
        return this.readValues(p, this._typeFactory.constructType(valueTypeRef));
    }

    public JsonNode readTree(InputStream in) throws IOException {
        this._assertNotNull("in", in);
        return this._readTreeAndClose(this._jsonFactory.createParser(in));
    }

    public JsonNode readTree(Reader r) throws IOException {
        this._assertNotNull("r", r);
        return this._readTreeAndClose(this._jsonFactory.createParser(r));
    }

    public JsonNode readTree(String content) throws JsonProcessingException, JsonMappingException {
        this._assertNotNull("content", content);

        try {
            return this._readTreeAndClose(this._jsonFactory.createParser(content));
        } catch (JsonProcessingException var3) {
            throw var3;
        } catch (IOException var4) {
            throw JsonMappingException.fromUnexpectedIOE(var4);
        }
    }

    public JsonNode readTree(byte[] content) throws IOException {
        this._assertNotNull("content", content);
        return this._readTreeAndClose(this._jsonFactory.createParser(content));
    }

    public JsonNode readTree(byte[] content, int offset, int len) throws IOException {
        this._assertNotNull("content", content);
        return this._readTreeAndClose(this._jsonFactory.createParser(content, offset, len));
    }

    public JsonNode readTree(File file) throws IOException {
        this._assertNotNull("file", file);
        return this._readTreeAndClose(this._jsonFactory.createParser(file));
    }

    public JsonNode readTree(URL source) throws IOException {
        this._assertNotNull("source", source);
        return this._readTreeAndClose(this._jsonFactory.createParser(source));
    }

    public void writeValue(JsonGenerator g, Object value) throws IOException, StreamWriteException, DatabindException {
        this._assertNotNull("g", g);
        SerializationConfig config = this.getSerializationConfig();
        if (config.isEnabled(SerializationFeature.INDENT_OUTPUT) && g.getPrettyPrinter() == null) {
            g.setPrettyPrinter(config.constructDefaultPrettyPrinter());
        }

        if (config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && value instanceof Closeable) {
            this._writeCloseableValue(g, value, config);
        } else {
            this._serializerProvider(config).serializeValue(g, value);
            if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
                g.flush();
            }
        }

    }

    public void writeTree(JsonGenerator g, TreeNode rootNode) throws IOException {
        this._assertNotNull("g", g);
        SerializationConfig config = this.getSerializationConfig();
        this._serializerProvider(config).serializeValue(g, rootNode);
        if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
            g.flush();
        }

    }

    public void writeTree(JsonGenerator g, JsonNode rootNode) throws IOException {
        this._assertNotNull("g", g);
        SerializationConfig config = this.getSerializationConfig();
        this._serializerProvider(config).serializeValue(g, rootNode);
        if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
            g.flush();
        }

    }

    public ObjectNode createObjectNode() {
        return this._deserializationConfig.getNodeFactory().objectNode();
    }

    public ArrayNode createArrayNode() {
        return this._deserializationConfig.getNodeFactory().arrayNode();
    }

    public JsonNode missingNode() {
        return this._deserializationConfig.getNodeFactory().missingNode();
    }

    public JsonNode nullNode() {
        return this._deserializationConfig.getNodeFactory().nullNode();
    }

    public JsonParser treeAsTokens(TreeNode n) {
        this._assertNotNull("n", n);
        return new TreeTraversingParser((JsonNode)n, this);
    }

    public <T> T treeToValue(TreeNode n, Class<T> valueType) throws IllegalArgumentException, JsonProcessingException {
        if (n == null) {
            return null;
        } else {
            try {
                if (TreeNode.class.isAssignableFrom(valueType) && valueType.isAssignableFrom(n.getClass())) {
                    return n;
                } else {
                    JsonToken tt = n.asToken();
                    if (tt == JsonToken.VALUE_EMBEDDED_OBJECT && n instanceof POJONode) {
                        Object ob = ((POJONode)n).getPojo();
                        if (ob == null || valueType.isInstance(ob)) {
                            return ob;
                        }
                    }

                    return this.readValue(this.treeAsTokens(n), valueType);
                }
            } catch (JsonProcessingException var5) {
                throw var5;
            } catch (IOException var6) {
                throw new IllegalArgumentException(var6.getMessage(), var6);
            }
        }
    }

    public <T> T treeToValue(TreeNode n, JavaType valueType) throws IllegalArgumentException, JsonProcessingException {
        if (n == null) {
            return null;
        } else {
            try {
                if (valueType.isTypeOrSubTypeOf(TreeNode.class) && valueType.isTypeOrSuperTypeOf(n.getClass())) {
                    return n;
                } else {
                    JsonToken tt = n.asToken();
                    if (tt == JsonToken.VALUE_EMBEDDED_OBJECT && n instanceof POJONode) {
                        Object ob = ((POJONode)n).getPojo();
                        if (ob == null || valueType.isTypeOrSuperTypeOf(ob.getClass())) {
                            return ob;
                        }
                    }

                    return this.readValue(this.treeAsTokens(n), valueType);
                }
            } catch (JsonProcessingException var5) {
                throw var5;
            } catch (IOException var6) {
                throw new IllegalArgumentException(var6.getMessage(), var6);
            }
        }
    }

    public <T extends JsonNode> T valueToTree(Object fromValue) throws IllegalArgumentException {
        if (fromValue == null) {
            return this.getNodeFactory().nullNode();
        } else {
            SerializationConfig config = this.getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE);
            DefaultSerializerProvider context = this._serializerProvider(config);
            TokenBuffer buf = context.bufferForValueConversion(this);
            if (this.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                buf = buf.forceUseOfBigDecimal(true);
            }

            try {
                context.serializeValue(buf, fromValue);
                JsonParser p = buf.asParser();
                Throwable var6 = null;

                JsonNode var7;
                try {
                    var7 = (JsonNode)this.readTree(p);
                } catch (Throwable var17) {
                    var6 = var17;
                    throw var17;
                } finally {
                    if (p != null) {
                        if (var6 != null) {
                            try {
                                p.close();
                            } catch (Throwable var16) {
                                var6.addSuppressed(var16);
                            }
                        } else {
                            p.close();
                        }
                    }

                }

                return var7;
            } catch (IOException var19) {
                throw new IllegalArgumentException(var19.getMessage(), var19);
            }
        }
    }

    public boolean canSerialize(Class<?> type) {
        return this._serializerProvider(this.getSerializationConfig()).hasSerializerFor(type, (AtomicReference)null);
    }

    public boolean canSerialize(Class<?> type, AtomicReference<Throwable> cause) {
        return this._serializerProvider(this.getSerializationConfig()).hasSerializerFor(type, cause);
    }

    public boolean canDeserialize(JavaType type) {
        return this.createDeserializationContext((JsonParser)null, this.getDeserializationConfig()).hasValueDeserializerFor(type, (AtomicReference)null);
    }

    public boolean canDeserialize(JavaType type, AtomicReference<Throwable> cause) {
        return this.createDeserializationContext((JsonParser)null, this.getDeserializationConfig()).hasValueDeserializerFor(type, cause);
    }

    public <T> T readValue(File src, Class<T> valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(File src, TypeReference<T> valueTypeRef) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueTypeRef));
    }

    public <T> T readValue(File src, JavaType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), valueType);
    }

    public <T> T readValue(URL src, Class<T> valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(URL src, TypeReference<T> valueTypeRef) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueTypeRef));
    }

    public <T> T readValue(URL src, JavaType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), valueType);
    }

    public <T> T readValue(String content, Class<T> valueType) throws JsonProcessingException, JsonMappingException {
        this._assertNotNull("content", content);
        return this.readValue(content, this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(String content, TypeReference<T> valueTypeRef) throws JsonProcessingException, JsonMappingException {
        this._assertNotNull("content", content);
        return this.readValue(content, this._typeFactory.constructType(valueTypeRef));
    }

    public <T> T readValue(String content, JavaType valueType) throws JsonProcessingException, JsonMappingException {
        this._assertNotNull("content", content);

        try {
            return this._readMapAndClose(this._jsonFactory.createParser(content), valueType);
        } catch (JsonProcessingException var4) {
            throw var4;
        } catch (IOException var5) {
            throw JsonMappingException.fromUnexpectedIOE(var5);
        }
    }

    public <T> T readValue(Reader src, Class<T> valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(Reader src, TypeReference<T> valueTypeRef) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueTypeRef));
    }

    public <T> T readValue(Reader src, JavaType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), valueType);
    }

    public <T> T readValue(InputStream src, Class<T> valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(InputStream src, TypeReference<T> valueTypeRef) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueTypeRef));
    }

    public <T> T readValue(InputStream src, JavaType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), valueType);
    }

    public <T> T readValue(byte[] src, Class<T> valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(byte[] src, int offset, int len, Class<T> valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src, offset, len), this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(byte[] src, TypeReference<T> valueTypeRef) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueTypeRef));
    }

    public <T> T readValue(byte[] src, int offset, int len, TypeReference<T> valueTypeRef) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src, offset, len), this._typeFactory.constructType(valueTypeRef));
    }

    public <T> T readValue(byte[] src, JavaType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), valueType);
    }

    public <T> T readValue(byte[] src, int offset, int len, JavaType valueType) throws IOException, StreamReadException, DatabindException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src, offset, len), valueType);
    }

    public <T> T readValue(DataInput src, Class<T> valueType) throws IOException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), this._typeFactory.constructType(valueType));
    }

    public <T> T readValue(DataInput src, JavaType valueType) throws IOException {
        this._assertNotNull("src", src);
        return this._readMapAndClose(this._jsonFactory.createParser(src), valueType);
    }

    public void writeValue(File resultFile, Object value) throws IOException, StreamWriteException, DatabindException {
        this._writeValueAndClose(this.createGenerator(resultFile, JsonEncoding.UTF8), value);
    }

    public void writeValue(OutputStream out, Object value) throws IOException, StreamWriteException, DatabindException {
        this._writeValueAndClose(this.createGenerator(out, JsonEncoding.UTF8), value);
    }

    public void writeValue(DataOutput out, Object value) throws IOException {
        this._writeValueAndClose(this.createGenerator(out), value);
    }

    public void writeValue(Writer w, Object value) throws IOException, StreamWriteException, DatabindException {
        this._writeValueAndClose(this.createGenerator(w), value);
    }

    public String writeValueAsString(Object value) throws JsonProcessingException {
        SegmentedStringWriter sw = new SegmentedStringWriter(this._jsonFactory._getBufferRecycler());

        try {
            this._writeValueAndClose(this.createGenerator((Writer)sw), value);
        } catch (JsonProcessingException var4) {
            throw var4;
        } catch (IOException var5) {
            throw JsonMappingException.fromUnexpectedIOE(var5);
        }

        return sw.getAndClear();
    }

    public byte[] writeValueAsBytes(Object value) throws JsonProcessingException {
        try {
            ByteArrayBuilder bb = new ByteArrayBuilder(this._jsonFactory._getBufferRecycler());
            Throwable var3 = null;

            byte[] var5;
            try {
                this._writeValueAndClose(this.createGenerator((OutputStream)bb, JsonEncoding.UTF8), value);
                byte[] result = bb.toByteArray();
                bb.release();
                var5 = result;
            } catch (Throwable var16) {
                var3 = var16;
                throw var16;
            } finally {
                if (bb != null) {
                    if (var3 != null) {
                        try {
                            bb.close();
                        } catch (Throwable var15) {
                            var3.addSuppressed(var15);
                        }
                    } else {
                        bb.close();
                    }
                }

            }

            return var5;
        } catch (JsonProcessingException var18) {
            throw var18;
        } catch (IOException var19) {
            throw JsonMappingException.fromUnexpectedIOE(var19);
        }
    }

    public ObjectWriter writer() {
        return this._newWriter(this.getSerializationConfig());
    }

    public ObjectWriter writer(SerializationFeature feature) {
        return this._newWriter(this.getSerializationConfig().with(feature));
    }

    public ObjectWriter writer(SerializationFeature first, SerializationFeature... other) {
        return this._newWriter(this.getSerializationConfig().with(first, other));
    }

    public ObjectWriter writer(DateFormat df) {
        return this._newWriter(this.getSerializationConfig().with(df));
    }

    public ObjectWriter writerWithView(Class<?> serializationView) {
        return this._newWriter(this.getSerializationConfig().withView(serializationView));
    }

    public ObjectWriter writerFor(Class<?> rootType) {
        return this._newWriter(this.getSerializationConfig(), rootType == null ? null : this._typeFactory.constructType(rootType), (PrettyPrinter)null);
    }

    public ObjectWriter writerFor(TypeReference<?> rootType) {
        return this._newWriter(this.getSerializationConfig(), rootType == null ? null : this._typeFactory.constructType(rootType), (PrettyPrinter)null);
    }

    public ObjectWriter writerFor(JavaType rootType) {
        return this._newWriter(this.getSerializationConfig(), rootType, (PrettyPrinter)null);
    }

    public ObjectWriter writer(PrettyPrinter pp) {
        if (pp == null) {
            pp = ObjectWriter.NULL_PRETTY_PRINTER;
        }

        return this._newWriter(this.getSerializationConfig(), (JavaType)null, pp);
    }

    public ObjectWriter writerWithDefaultPrettyPrinter() {
        SerializationConfig config = this.getSerializationConfig();
        return this._newWriter(config, (JavaType)null, config.getDefaultPrettyPrinter());
    }

    public ObjectWriter writer(FilterProvider filterProvider) {
        return this._newWriter(this.getSerializationConfig().withFilters(filterProvider));
    }

    public ObjectWriter writer(FormatSchema schema) {
        this._verifySchemaType(schema);
        return this._newWriter(this.getSerializationConfig(), schema);
    }

    public ObjectWriter writer(Base64Variant defaultBase64) {
        return this._newWriter((SerializationConfig)this.getSerializationConfig().with(defaultBase64));
    }

    public ObjectWriter writer(CharacterEscapes escapes) {
        return this._newWriter(this.getSerializationConfig()).with(escapes);
    }

    public ObjectWriter writer(ContextAttributes attrs) {
        return this._newWriter(this.getSerializationConfig().with(attrs));
    }

    /** @deprecated */
    @Deprecated
    public ObjectWriter writerWithType(Class<?> rootType) {
        return this._newWriter(this.getSerializationConfig(), rootType == null ? null : this._typeFactory.constructType(rootType), (PrettyPrinter)null);
    }

    /** @deprecated */
    @Deprecated
    public ObjectWriter writerWithType(TypeReference<?> rootType) {
        return this._newWriter(this.getSerializationConfig(), rootType == null ? null : this._typeFactory.constructType(rootType), (PrettyPrinter)null);
    }

    /** @deprecated */
    @Deprecated
    public ObjectWriter writerWithType(JavaType rootType) {
        return this._newWriter(this.getSerializationConfig(), rootType, (PrettyPrinter)null);
    }

    public ObjectReader reader() {
        return this._newReader(this.getDeserializationConfig()).with(this._injectableValues);
    }

    public ObjectReader reader(DeserializationFeature feature) {
        return this._newReader(this.getDeserializationConfig().with(feature));
    }

    public ObjectReader reader(DeserializationFeature first, DeserializationFeature... other) {
        return this._newReader(this.getDeserializationConfig().with(first, other));
    }

    public ObjectReader readerForUpdating(Object valueToUpdate) {
        JavaType t = valueToUpdate == null ? null : this._typeFactory.constructType(valueToUpdate.getClass());
        return this._newReader(this.getDeserializationConfig(), t, valueToUpdate, (FormatSchema)null, this._injectableValues);
    }

    public ObjectReader readerFor(JavaType type) {
        return this._newReader(this.getDeserializationConfig(), type, (Object)null, (FormatSchema)null, this._injectableValues);
    }

    public ObjectReader readerFor(Class<?> type) {
        JavaType t = type == null ? null : this._typeFactory.constructType(type);
        return this._newReader(this.getDeserializationConfig(), t, (Object)null, (FormatSchema)null, this._injectableValues);
    }

    public ObjectReader readerFor(TypeReference<?> typeRef) {
        this._assertNotNull("type", typeRef);
        return this._newReader(this.getDeserializationConfig(), this._typeFactory.constructType(typeRef), (Object)null, (FormatSchema)null, this._injectableValues);
    }

    public ObjectReader readerForArrayOf(Class<?> type) {
        this._assertNotNull("type", type);
        return this._newReader(this.getDeserializationConfig(), this._typeFactory.constructArrayType(type), (Object)null, (FormatSchema)null, this._injectableValues);
    }

    public ObjectReader readerForListOf(Class<?> type) {
        this._assertNotNull("type", type);
        return this._newReader(this.getDeserializationConfig(), this._typeFactory.constructCollectionType(List.class, type), (Object)null, (FormatSchema)null, this._injectableValues);
    }

    public ObjectReader readerForMapOf(Class<?> type) {
        this._assertNotNull("type", type);
        return this._newReader(this.getDeserializationConfig(), this._typeFactory.constructMapType(Map.class, String.class, type), (Object)null, (FormatSchema)null, this._injectableValues);
    }

    public ObjectReader reader(JsonNodeFactory nodeFactory) {
        this._assertNotNull("nodeFactory", nodeFactory);
        return this._newReader(this.getDeserializationConfig()).with(nodeFactory);
    }

    public ObjectReader reader(FormatSchema schema) {
        this._verifySchemaType(schema);
        return this._newReader(this.getDeserializationConfig(), (JavaType)null, (Object)null, schema, this._injectableValues);
    }

    public ObjectReader reader(InjectableValues injectableValues) {
        return this._newReader(this.getDeserializationConfig(), (JavaType)null, (Object)null, (FormatSchema)null, injectableValues);
    }

    public ObjectReader readerWithView(Class<?> view) {
        return this._newReader(this.getDeserializationConfig().withView(view));
    }

    public ObjectReader reader(Base64Variant defaultBase64) {
        return this._newReader((DeserializationConfig)this.getDeserializationConfig().with(defaultBase64));
    }

    public ObjectReader reader(ContextAttributes attrs) {
        return this._newReader(this.getDeserializationConfig().with(attrs));
    }

    /** @deprecated */
    @Deprecated
    public ObjectReader reader(JavaType type) {
        return this._newReader(this.getDeserializationConfig(), type, (Object)null, (FormatSchema)null, this._injectableValues);
    }

    /** @deprecated */
    @Deprecated
    public ObjectReader reader(Class<?> type) {
        return this._newReader(this.getDeserializationConfig(), this._typeFactory.constructType(type), (Object)null, (FormatSchema)null, this._injectableValues);
    }

    /** @deprecated */
    @Deprecated
    public ObjectReader reader(TypeReference<?> type) {
        return this._newReader(this.getDeserializationConfig(), this._typeFactory.constructType(type), (Object)null, (FormatSchema)null, this._injectableValues);
    }

    public <T> T convertValue(Object fromValue, Class<T> toValueType) throws IllegalArgumentException {
        return this._convert(fromValue, this._typeFactory.constructType(toValueType));
    }

    public <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef) throws IllegalArgumentException {
        return this._convert(fromValue, this._typeFactory.constructType(toValueTypeRef));
    }

    public <T> T convertValue(Object fromValue, JavaType toValueType) throws IllegalArgumentException {
        return this._convert(fromValue, toValueType);
    }

    protected Object _convert(Object fromValue, JavaType toValueType) throws IllegalArgumentException {
        SerializationConfig config = this.getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE);
        DefaultSerializerProvider context = this._serializerProvider(config);
        TokenBuffer buf = context.bufferForValueConversion(this);
        if (this.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
            buf = buf.forceUseOfBigDecimal(true);
        }

        try {
            context.serializeValue(buf, fromValue);
            JsonParser p = buf.asParser();
            DeserializationConfig deserConfig = this.getDeserializationConfig();
            JsonToken t = this._initForReading(p, toValueType);
            Object result;
            DefaultDeserializationContext ctxt;
            if (t == JsonToken.VALUE_NULL) {
                ctxt = this.createDeserializationContext(p, deserConfig);
                result = this._findRootDeserializer(ctxt, toValueType).getNullValue(ctxt);
            } else if (t != JsonToken.END_ARRAY && t != JsonToken.END_OBJECT) {
                ctxt = this.createDeserializationContext(p, deserConfig);
                JsonDeserializer<Object> deser = this._findRootDeserializer(ctxt, toValueType);
                result = deser.deserialize(p, ctxt);
            } else {
                result = null;
            }

            p.close();
            return result;
        } catch (IOException var12) {
            throw new IllegalArgumentException(var12.getMessage(), var12);
        }
    }

    public <T> T updateValue(T valueToUpdate, Object overrides) throws JsonMappingException {
        T result = valueToUpdate;
        if (valueToUpdate != null && overrides != null) {
            SerializationConfig config = this.getSerializationConfig().without(SerializationFeature.WRAP_ROOT_VALUE);
            DefaultSerializerProvider context = this._serializerProvider(config);
            TokenBuffer buf = context.bufferForValueConversion(this);
            if (this.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
                buf = buf.forceUseOfBigDecimal(true);
            }

            try {
                context.serializeValue(buf, overrides);
                JsonParser p = buf.asParser();
                result = this.readerForUpdating(valueToUpdate).readValue(p);
                p.close();
            } catch (IOException var8) {
                if (var8 instanceof JsonMappingException) {
                    throw (JsonMappingException)var8;
                }

                throw JsonMappingException.fromUnexpectedIOE(var8);
            }
        }

        return result;
    }

    /** @deprecated */
    @Deprecated
    public JsonSchema generateJsonSchema(Class<?> t) throws JsonMappingException {
        return this._serializerProvider(this.getSerializationConfig()).generateJsonSchema(t);
    }

    public void acceptJsonFormatVisitor(Class<?> type, JsonFormatVisitorWrapper visitor) throws JsonMappingException {
        this.acceptJsonFormatVisitor(this._typeFactory.constructType(type), visitor);
    }

    public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor) throws JsonMappingException {
        if (type == null) {
            throw new IllegalArgumentException("type must be provided");
        } else {
            this._serializerProvider(this.getSerializationConfig()).acceptJsonFormatVisitor(type, visitor);
        }
    }

    protected TypeResolverBuilder<?> _constructDefaultTypeResolverBuilder(DefaultTyping applicability, PolymorphicTypeValidator ptv) {
        return ObjectMapper.DefaultTypeResolverBuilder.construct(applicability, ptv);
    }

    protected DefaultSerializerProvider _serializerProvider(SerializationConfig config) {
        return this._serializerProvider.createInstance(config, this._serializerFactory);
    }

    protected final void _writeValueAndClose(JsonGenerator g, Object value) throws IOException {
        SerializationConfig cfg = this.getSerializationConfig();
        if (cfg.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && value instanceof Closeable) {
            this._writeCloseable(g, value, cfg);
        } else {
            try {
                this._serializerProvider(cfg).serializeValue(g, value);
            } catch (Exception var5) {
                ClassUtil.closeOnFailAndThrowAsIOE(g, var5);
                return;
            }

            g.close();
        }
    }

    private final void _writeCloseable(JsonGenerator g, Object value, SerializationConfig cfg) throws IOException {
        Closeable toClose = (Closeable)value;

        try {
            this._serializerProvider(cfg).serializeValue(g, value);
            Closeable tmpToClose = toClose;
            toClose = null;
            tmpToClose.close();
        } catch (Exception var6) {
            ClassUtil.closeOnFailAndThrowAsIOE(g, toClose, var6);
            return;
        }

        g.close();
    }

    private final void _writeCloseableValue(JsonGenerator g, Object value, SerializationConfig cfg) throws IOException {
        Closeable toClose = (Closeable)value;

        try {
            this._serializerProvider(cfg).serializeValue(g, value);
            if (cfg.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
                g.flush();
            }
        } catch (Exception var6) {
            ClassUtil.closeOnFailAndThrowAsIOE((JsonGenerator)null, toClose, var6);
            return;
        }

        toClose.close();
    }

    /** @deprecated */
    @Deprecated
    protected final void _configAndWriteValue(JsonGenerator g, Object value) throws IOException {
        this.getSerializationConfig().initialize(g);
        this._writeValueAndClose(g, value);
    }

    protected Object _readValue(DeserializationConfig cfg, JsonParser p, JavaType valueType) throws IOException {
        JsonToken t = this._initForReading(p, valueType);
        DefaultDeserializationContext ctxt = this.createDeserializationContext(p, cfg);
        Object result;
        if (t == JsonToken.VALUE_NULL) {
            result = this._findRootDeserializer(ctxt, valueType).getNullValue(ctxt);
        } else if (t != JsonToken.END_ARRAY && t != JsonToken.END_OBJECT) {
            result = ctxt.readRootValue(p, valueType, this._findRootDeserializer(ctxt, valueType), (Object)null);
        } else {
            result = null;
        }

        p.clearCurrentToken();
        if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
            this._verifyNoTrailingTokens(p, ctxt, valueType);
        }

        return result;
    }

    protected Object _readMapAndClose(JsonParser p0, JavaType valueType) throws IOException {
        JsonParser p = p0;
        Throwable var4 = null;

        Object var9;
        try {
            DeserializationConfig cfg = this.getDeserializationConfig();
            DefaultDeserializationContext ctxt = this.createDeserializationContext(p, cfg);
            JsonToken t = this._initForReading(p, valueType);
            Object result;
            if (t == JsonToken.VALUE_NULL) {
                result = this._findRootDeserializer(ctxt, valueType).getNullValue(ctxt);
            } else if (t != JsonToken.END_ARRAY && t != JsonToken.END_OBJECT) {
                result = ctxt.readRootValue(p, valueType, this._findRootDeserializer(ctxt, valueType), (Object)null);
                ctxt.checkUnresolvedObjectId();
            } else {
                result = null;
            }

            if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
                this._verifyNoTrailingTokens(p, ctxt, valueType);
            }

            var9 = result;
        } catch (Throwable var18) {
            var4 = var18;
            throw var18;
        } finally {
            if (p0 != null) {
                if (var4 != null) {
                    try {
                        p.close();
                    } catch (Throwable var17) {
                        var4.addSuppressed(var17);
                    }
                } else {
                    p0.close();
                }
            }

        }

        return var9;
    }

    protected JsonNode _readTreeAndClose(JsonParser p0) throws IOException {
        JsonParser p = p0;
        Throwable var3 = null;

        try {
            JavaType valueType = this.constructType((Type)JsonNode.class);
            DeserializationConfig cfg = this.getDeserializationConfig();
            cfg.initialize(p);
            JsonToken t = p.currentToken();
            if (t == null) {
                t = p.nextToken();
                if (t == null) {
                    JsonNode var21 = cfg.getNodeFactory().missingNode();
                    return var21;
                }
            }

            DefaultDeserializationContext ctxt = this.createDeserializationContext(p, cfg);
            Object resultNode;
            if (t == JsonToken.VALUE_NULL) {
                resultNode = cfg.getNodeFactory().nullNode();
            } else {
                resultNode = (JsonNode)ctxt.readRootValue(p, valueType, this._findRootDeserializer(ctxt, valueType), (Object)null);
            }

            if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
                this._verifyNoTrailingTokens(p, ctxt, valueType);
            }

            Object var9 = resultNode;
            return (JsonNode)var9;
        } catch (Throwable var19) {
            var3 = var19;
            throw var19;
        } finally {
            if (p0 != null) {
                if (var3 != null) {
                    try {
                        p.close();
                    } catch (Throwable var18) {
                        var3.addSuppressed(var18);
                    }
                } else {
                    p0.close();
                }
            }

        }
    }

    protected DefaultDeserializationContext createDeserializationContext(JsonParser p, DeserializationConfig cfg) {
        return this._deserializationContext.createInstance(cfg, p, this._injectableValues);
    }

    protected JsonToken _initForReading(JsonParser p, JavaType targetType) throws IOException {
        this._deserializationConfig.initialize(p);
        JsonToken t = p.currentToken();
        if (t == null) {
            t = p.nextToken();
            if (t == null) {
                throw MismatchedInputException.from(p, targetType, "No content to map due to end-of-input");
            }
        }

        return t;
    }

    protected final void _verifyNoTrailingTokens(JsonParser p, DeserializationContext ctxt, JavaType bindType) throws IOException {
        JsonToken t = p.nextToken();
        if (t != null) {
            Class<?> bt = ClassUtil.rawClass(bindType);
            ctxt.reportTrailingTokens(bt, p, t);
        }

    }

    protected JsonDeserializer<Object> _findRootDeserializer(DeserializationContext ctxt, JavaType valueType) throws DatabindException {
        JsonDeserializer<Object> deser = (JsonDeserializer)this._rootDeserializers.get(valueType);
        if (deser != null) {
            return deser;
        } else {
            deser = ctxt.findRootValueDeserializer(valueType);
            if (deser == null) {
                return (JsonDeserializer)ctxt.reportBadDefinition(valueType, "Cannot find a deserializer for type " + valueType);
            } else {
                this._rootDeserializers.put(valueType, deser);
                return deser;
            }
        }
    }

    protected void _verifySchemaType(FormatSchema schema) {
        if (schema != null && !this._jsonFactory.canUseSchema(schema)) {
            throw new IllegalArgumentException("Cannot use FormatSchema of type " + schema.getClass().getName() + " for format " + this._jsonFactory.getFormatName());
        }
    }

    protected final void _assertNotNull(String paramName, Object src) {
        if (src == null) {
            throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));
        }
    }

    static {
        DEFAULT_BASE = new BaseSettings((ClassIntrospector)null, DEFAULT_ANNOTATION_INTROSPECTOR, (PropertyNamingStrategy)null, TypeFactory.defaultInstance(), (TypeResolverBuilder)null, StdDateFormat.instance, (HandlerInstantiator)null, Locale.getDefault(), (TimeZone)null, Base64Variants.getDefaultVariant(), LaissezFaireSubTypeValidator.instance, new DefaultAccessorNamingStrategy.Provider());
    }

    public static class DefaultTypeResolverBuilder extends StdTypeResolverBuilder implements Serializable {
        private static final long serialVersionUID = 1L;
        protected final DefaultTyping _appliesFor;
        protected final PolymorphicTypeValidator _subtypeValidator;

        /** @deprecated */
        @Deprecated
        public DefaultTypeResolverBuilder(DefaultTyping t) {
            this((DefaultTyping)t, (PolymorphicTypeValidator)LaissezFaireSubTypeValidator.instance);
        }

        public DefaultTypeResolverBuilder(DefaultTyping t, PolymorphicTypeValidator ptv) {
            this._appliesFor = (DefaultTyping)_requireNonNull(t, "Can not pass `null` DefaultTyping");
            this._subtypeValidator = (PolymorphicTypeValidator)_requireNonNull(ptv, "Can not pass `null` PolymorphicTypeValidator");
        }

        protected DefaultTypeResolverBuilder(DefaultTypeResolverBuilder base, Class<?> defaultImpl) {
            super(base, defaultImpl);
            this._appliesFor = base._appliesFor;
            this._subtypeValidator = base._subtypeValidator;
        }

        private static <T> T _requireNonNull(T value, String msg) {
            if (value == null) {
                throw new NullPointerException(msg);
            } else {
                return value;
            }
        }

        public static DefaultTypeResolverBuilder construct(DefaultTyping t, PolymorphicTypeValidator ptv) {
            return new DefaultTypeResolverBuilder(t, ptv);
        }

        public DefaultTypeResolverBuilder withDefaultImpl(Class<?> defaultImpl) {
            if (this._defaultImpl == defaultImpl) {
                return this;
            } else {
                ClassUtil.verifyMustOverride(DefaultTypeResolverBuilder.class, this, "withDefaultImpl");
                return new DefaultTypeResolverBuilder(this, defaultImpl);
            }
        }

        public PolymorphicTypeValidator subTypeValidator(MapperConfig<?> config) {
            return this._subtypeValidator;
        }

        public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, JavaType baseType, Collection<NamedType> subtypes) {
            return this.useForType(baseType) ? super.buildTypeDeserializer(config, baseType, subtypes) : null;
        }

        public TypeSerializer buildTypeSerializer(SerializationConfig config, JavaType baseType, Collection<NamedType> subtypes) {
            return this.useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes) : null;
        }

        public boolean useForType(JavaType t) {
            if (t.isPrimitive()) {
                return false;
            } else {
                switch (this._appliesFor) {
                    case NON_CONCRETE_AND_ARRAYS:
                        while(t.isArrayType()) {
                            t = t.getContentType();
                        }
                    case OBJECT_AND_NON_CONCRETE:
                        break;
                    case NON_FINAL:
                        while(t.isArrayType()) {
                            t = t.getContentType();
                        }

                        while(t.isReferenceType()) {
                            t = t.getReferencedType();
                        }

                        return !t.isFinal() && !TreeNode.class.isAssignableFrom(t.getRawClass());
                    case EVERYTHING:
                        return true;
                    case JAVA_LANG_OBJECT:
                    default:
                        return t.isJavaLangObject();
                }

                while(t.isReferenceType()) {
                    t = t.getReferencedType();
                }

                return t.isJavaLangObject() || !t.isConcrete() && !TreeNode.class.isAssignableFrom(t.getRawClass());
            }
        }
    }

    public static enum DefaultTyping {
        JAVA_LANG_OBJECT,
        OBJECT_AND_NON_CONCRETE,
        NON_CONCRETE_AND_ARRAYS,
        NON_FINAL,
        EVERYTHING;

        private DefaultTyping() {
        }
    }
}
<file_sep>/home/user/IdeaProjects/MovieLand/movieland-backend/src/main/java/com/phil/movieland/rest/service/MovieUtils.java 
<fim_prefix>public List<Movie> getMoviesSortedByPlaytime(String name) {
        var o = new ObjectMapper();
        return IntStream.range(0,10) <fim_suffix> 
    }<fim_middle>

I think in general the decompiled code should still be usable for the LLMs, although obviously the actual source code would be better.
You can also see the other changes in the example prompt, only the code snippets of the classes/methods is included, there are e.g. no import statements. Also the IntStream.range() is not added either, since its part of the JDK. A major concern is how we limit the prompt/context size, especially when Classes are referenced, can we somehow evaluate what parts of the class is relevant? Do we limit the amount of referenced classes/methods?

Also you can see that since in the FIM prompt itself there is only the method getMoviesSortedByPlaytime, the class field movieService is not present anymore, so the LLM would probably give a faulty/unuseful completion.

if (enclosingContext is PsiClass) {
// add class and instance fields of enclosing class
// TODO: class fields declarations have to be present in the infillPrompt
// (same file as enclosingElement) as well
resultSet.addAll(
findRelevantElements(
(element.parent as PsiClass).allFields.toSet(),
rootElement

We would somehow have to build the infillPrompt with the enclosingElement but also with any other relevant fields in the same class/file

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in general the decompiled code should still be usable for the LLMs, although obviously the actual source code would be better.

I think it's fine, let's keep it for now.

A major concern is how we limit the prompt/context size, especially when Classes are referenced, can we somehow evaluate what parts of the class is relevant? Do we limit the amount of referenced classes/methods?

This is difficult. I think we need to set some maximum token limit boundaries, and even without the class references, some of the context may be left out or even worse, cut out. So, there needs to exist some kind of reranking mechanism to filter out irrelevant data. For now, could we just filter out the class elements?

Also you can see that since in the FIM prompt itself there is only the method getMoviesSortedByPlaytime, the class field movieService is not present anymore, so the LLM would probably give a faulty/unuseful completion.

Would it be possible to provide the class name or file path from which the getMoviesSortedByPlaytime method is coming? For example, instead of passing in the list of PsiTargets, you could forward a mapping where the key points to class details and the value to its methods/functions?

return if (infillDetails.context == null || infillDetails.context.contextFiles.isNullOrEmpty()) {
infillPrompt
} else {
"<reponame>${infillDetails.context.repoName}" +
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really cool! I didn't know it was possible to give in additional knowledge like this 👍

val prefix: String = truncateText(document, start, caretOffset, false)
val suffix: String = truncateText(document, caretOffset, end, true)
return InfillRequestDetails(prefix, suffix)
val truncatedPrefix = prefix.takeLast(MAX_OFFSET)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to find a better solution for this MAX_OFFSET because 10,000 chars is a lot, especially since we're now providing more additional context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes definetely, perhaps we need to leverage the PSI tree to limit the completion to e.g. method or class level, depending on how big the file is. I remember I implemented the code completions in the beginning with limiting it to method-level instead of sending the entire file

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I remember something similar. However, having just a method-level context isn't sufficient without the relevant context.

@PhilKes
Copy link
Contributor Author

PhilKes commented May 26, 2024

In theory we could also add library source code to the prompt since they can be evaluated with PSI as well. Since models are only trained on specific timestamps, this could be used to "keep them up-to-date" with newer library source code

Yes, and I think we should already include this change in the current branch. This shouldn't require any additional implementation IF you remove the PsiTarget -> VirtualFile mapping and take the content directly from the PSI element.

Getting the text contents from the PsiTarget does work, but for library code it will not return the source code, but the compiled code. For example if I have a reference to Jackson's ObjectMapper the text content of its PsiTarget/PsiClassImpl is:

PsiClassImpl#ObjectMapper
public class ObjectMapper extends com.fasterxml.jackson.core.ObjectCodec implements com.fasterxml.jackson.core.Versioned, java.io.Serializable {
    private static final long serialVersionUID = 2L;
    protected static final com.fasterxml.jackson.databind.AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR;
    protected static final com.fasterxml.jackson.databind.cfg.BaseSettings DEFAULT_BASE;
    protected final com.fasterxml.jackson.core.JsonFactory _jsonFactory;
    protected com.fasterxml.jackson.databind.type.TypeFactory _typeFactory;
    protected com.fasterxml.jackson.databind.InjectableValues _injectableValues;
    protected com.fasterxml.jackson.databind.jsontype.SubtypeResolver _subtypeResolver;
    protected final com.fasterxml.jackson.databind.cfg.ConfigOverrides _configOverrides;
    protected final com.fasterxml.jackson.databind.cfg.CoercionConfigs _coercionConfigs;
    protected com.fasterxml.jackson.databind.introspect.SimpleMixInResolver _mixIns;
    protected com.fasterxml.jackson.databind.SerializationConfig _serializationConfig;
    protected com.fasterxml.jackson.databind.ser.DefaultSerializerProvider _serializerProvider;
    protected com.fasterxml.jackson.databind.ser.SerializerFactory _serializerFactory;
    protected com.fasterxml.jackson.databind.DeserializationConfig _deserializationConfig;
    protected com.fasterxml.jackson.databind.deser.DefaultDeserializationContext _deserializationContext;
    protected java.util.Set<java.lang.Object> _registeredModuleTypes;
    protected final java.util.concurrent.ConcurrentHashMap<com.fasterxml.jackson.databind.JavaType,com.fasterxml.jackson.databind.JsonDeserializer<java.lang.Object>> _rootDeserializers;

    public ObjectMapper() { /* compiled code */ }

    public ObjectMapper(com.fasterxml.jackson.core.JsonFactory jf) { /* compiled code */ }

    protected ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper src) { /* compiled code */ }

    protected ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper src, com.fasterxml.jackson.core.JsonFactory factory) { /* compiled code */ }

    public ObjectMapper(com.fasterxml.jackson.core.JsonFactory jf, com.fasterxml.jackson.databind.ser.DefaultSerializerProvider sp, com.fasterxml.jackson.databind.deser.DefaultDeserializationContext dc) { /* compiled code */ }

    protected com.fasterxml.jackson.databind.introspect.ClassIntrospector defaultClassIntrospector() { /* compiled code */ }

    public com.fasterxml.jackson.databind.ObjectMapper copy() { /* compiled code */ }

    public com.fasterxml.jackson.databind.ObjectMapper copyWith(com.fasterxml.jackson.core.JsonFactory factory) { /* compiled code */ }

    protected void _checkInvalidCopy(java.lang.Class<?> exp) { /* compiled code */ }

    protected com.fasterxml.jackson.databind.ObjectReader _newReader(com.fasterxml.jackson.databind.DeserializationConfig config) { /* compiled code */ }

    protected com.fasterxml.jackson.databind.ObjectReader _newReader(com.fasterxml.jackson.databind.DeserializationConfig config, com.fasterxml.jackson.databind.JavaType valueType, java.lang.Object valueToUpdate, com.fasterxml.jackson.core.FormatSchema schema, com.fasterxml.jackson.databind.InjectableValues injectableValues) { /* compiled code */ }

    protected com.fasterxml.jackson.databind.ObjectWriter _newWriter(com.fasterxml.jackson.databind.SerializationConfig config) { /* compiled code */ }

    protected com.fasterxml.jackson.databind.ObjectWriter _newWriter(com.fasterxml.jackson.databind.SerializationConfig config, com.fasterxml.jackson.core.FormatSchema schema) { /* compiled code */ }

    protected com.fasterxml.jackson.databind.ObjectWriter _newWriter(com.fasterxml.jackson.databind.SerializationConfig config, com.fasterxml.jackson.databind.JavaType rootType, com.fasterxml.jackson.core.PrettyPrinter pp) { /* compiled code */ }

    public com.fasterxml.jackson.core.Version version() { /* compiled code */ }

    public com.fasterxml.jackson.databind.ObjectMapper registerModule(com.fasterxml.jackson.databind.Module module) { /* compiled code */ }
...
}

I think to get the actual source code it has to be downloaded first (for e.g. java usually libraries provide separate sources.jar, which is downloaded by DownloadSourcesAction

Which model is the best compromise between response time and completion quality?

Currently, most users are using the OpenAI provider, which means that gpt-3.5-turbo-instruct should be considered the primary model for code completions.

I haven't tested this with ChatGPT, as far as I know gpt-3.5-turbo-instruct was only trained with the FIM tokens, not repository-level completion tokens like the mentioned open source models. We would have to come up with our own syntax for prompting ChatGPT, although I am not sure how reliable that would be.

Should the user have an option to include/exclude this automatic context for code-completions?

I think so, similarly to how we allow users to enable/disable completion post-processing. Eventually, we can remove them altogether, as they can be relatively hard for users to understand.

I agree, I think customizability has been mentioned many times as one of the advantages of the CodeGPT plugin, so we should keep doing that. It will also take some time to find the best configuration either way.

@carlrobertoh
Copy link
Owner

Getting the text contents from the PsiTarget does work, but for library code it will not return the source code, but the compiled code. For example if I have a reference to Jackson's ObjectMapper the text content of its PsiTarget/PsiClassImpl is:

Ahh, ok. In that case, can we include the functionality only if the user has downloaded the source code?

@PhilKes
Copy link
Contributor Author

PhilKes commented May 27, 2024

Getting the text contents from the PsiTarget does work, but for library code it will not return the source code, but the compiled code. For example if I have a reference to Jackson's ObjectMapper the text content of its PsiTarget/PsiClassImpl is:

Ahh, ok. In that case, can we include the functionality only if the user has downloaded the source code?

For library code, yes. I am experimenting with triggering the download source action programatically, but I don't think thats a good solution. Perhaps we put a hint in the settings that its benefitial to enable Maven/Gradle auto-download of the sources, then all library sources that are available would be present at the time of the code-completion.
I also think this is just a problem with Java, since there is a separation between the compiled .jar and the sources.jar. If you e.g. go to the definition of some library code in JavaScript, or GoLang you end up directly in the sources. But I do not have an overview of which languages/package-managers have compiled library code and sources separately.
For now we could simply check if ClsMethodImpl.sourceMirrorMethod/ClsClassImpl.getSourceMirrorClass is present, if yes, we include the library code, if not, we ignore it?

We should also make a list of what languages we want to support for the 1st release of this feature.
There also IntelliJ plugins providing more specific PSI extensions for frameworks such as Spring, VueJS, Angular,... that we can add later on

@carlrobertoh
Copy link
Owner

For now we could simply check if ClsMethodImpl.sourceMirrorMethod/ClsClassImpl.getSourceMirrorClass is present, if yes, we include the library code, if not, we ignore it?

Yes, that would work. We can focus on it in a later phase.

There also IntelliJ plugins providing more specific PSI extensions for frameworks such as Spring, VueJS, Angular,... that we can add later on

Not sure what the impact on the extension's size would be when integrating with all of these plugins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants