private CompletableFuture getBaseLocationsAsync()

in src/main/java/com/jetbrains/jdi/ConcreteMethodImpl.java [548:623]


    private CompletableFuture<SoftLocationXRefs> getBaseLocationsAsync() {
        SoftLocationXRefs info = (softBaseLocationXRefsRef == null) ? null :
                softBaseLocationXRefsRef.get();
        if (info != null) {
            return CompletableFuture.completedFuture(info);
        }

        return JDWP.Method.LineTable.processAsync(vm, declaringType, ref)
                .thenApply(lntab -> {
                    int count = lntab.lines.length;

                    List<Location> lineLocations = new ArrayList<>(count);
                    Map<Integer, List<Location>> lineMapper = new HashMap<>();
                    int lowestLine = -1;
                    int highestLine = -1;
                    for (int i = 0; i < count; i++) {
                        long bci = lntab.lines[i].lineCodeIndex;
                        int lineNumber = lntab.lines[i].lineNumber;

                        /*
                         * Some compilers will point multiple consecutive
                         * lines at the same location. We need to choose
                         * one of them so that we can consistently map back
                         * and forth between line and location. So we choose
                         * to record only the last line entry at a particular
                         * location.
                         */
                        if ((i + 1 == count) || (bci != lntab.lines[i + 1].lineCodeIndex)) {
                            // Remember the largest/smallest line number
                            if (lineNumber > highestLine) {
                                highestLine = lineNumber;
                            }
                            if ((lineNumber < lowestLine) || (lowestLine == -1)) {
                                lowestLine = lineNumber;
                            }
                            LocationImpl loc =
                                    new LocationImpl(virtualMachine(), this, bci);
                            loc.addBaseLineInfo(
                                    new BaseLineInfo(lineNumber, declaringType));

                            // Add to the location list
                            lineLocations.add(loc);

                            // Add to the line -> locations map
                            lineMapper.computeIfAbsent(lineNumber, k -> new ArrayList<>(1)).add(loc);
                        }
                    }

                    /*
                     * firstIndex, lastIndex, and startLocation need to be
                     * retrieved only once since they are strongly referenced.
                     */
                    if (location == null) {
                        firstIndex = lntab.start;
                        lastIndex = lntab.end;
                        /*
                         * The startLocation is the first one in the
                         * location list if we have one;
                         * otherwise, we construct a location for a
                         * method start with no line info
                         */
                        if (count > 0) {
                            location = lineLocations.get(0);
                        } else {
                            location = new LocationImpl(virtualMachine(), this,
                                    firstIndex);
                        }
                    }

                    SoftLocationXRefs res = new SoftLocationXRefs(SDE.BASE_STRATUM_NAME,
                            lineMapper, lineLocations,
                            lowestLine, highestLine);
                    softBaseLocationXRefsRef = vm.createSoftReference(res);
                    return res;
                });
    }