mirror of
https://github.com/apple/pkl.git
synced 2026-06-30 02:01:54 +02:00
Fix many editor diagnostics (#1707)
This addresses many IDE warnings resulting from the switch to JSpecify. Also, this changes the behavior of exporting VmObject; there's no place in our code that does not force a VmObject prior to export, so the existing logic around handling nullable values has been removed.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -69,11 +69,11 @@ public record ImportGraph(Map<URI, Set<Import>> imports, Map<URI, URI> resolvedI
|
||||
var value = entry.getValue();
|
||||
var set = new TreeSet<Import>();
|
||||
if (!(value instanceof JsArray array)) {
|
||||
throw new FormatException("array", value.getClass());
|
||||
throw new FormatException("array", value == null ? Void.class : value.getClass());
|
||||
}
|
||||
for (var elem : array) {
|
||||
if (!(elem instanceof JsObject importObj)) {
|
||||
throw new FormatException("object", elem.getClass());
|
||||
throw new FormatException("object", elem == null ? Void.class : elem.getClass());
|
||||
}
|
||||
set.add(parseImport(importObj));
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public record ImportGraph(Map<URI, Set<Import>> imports, Map<URI, URI> resolvedI
|
||||
var key = new URI(entry.getKey());
|
||||
var value = entry.getValue();
|
||||
if (!(value instanceof String str)) {
|
||||
throw new FormatException("string", value.getClass());
|
||||
throw new FormatException("string", value == null ? Void.class : value.getClass());
|
||||
}
|
||||
var valueUri = new URI(str);
|
||||
ret.put(key, valueUri);
|
||||
|
||||
@@ -109,6 +109,8 @@ final class JsonRenderer implements ValueRenderer {
|
||||
"Values of type `Bytes` cannot be rendered as JSON. Value: %s", (Object) value));
|
||||
}
|
||||
|
||||
// Pair coming from the runtime can never admit null (in-language null is represented as PNull)
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@Override
|
||||
public void visitPair(Pair<?, ?> value) {
|
||||
try {
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.pkl.core;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/** Describes the property, method and class members of a module. */
|
||||
public final class ModuleSchema {
|
||||
@@ -33,8 +32,8 @@ public final class ModuleSchema {
|
||||
private final Map<String, TypeAlias> typeAliases;
|
||||
private final Map<String, URI> imports;
|
||||
|
||||
@LateInit private Map<String, PClass> __allClasses;
|
||||
@LateInit private Map<String, TypeAlias> __allTypeAliases;
|
||||
private @Nullable Map<String, PClass> __allClasses;
|
||||
private @Nullable Map<String, TypeAlias> __allTypeAliases;
|
||||
|
||||
/** Constructs a {@code ModuleSchema} instance. */
|
||||
public ModuleSchema(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -227,9 +227,7 @@ final class PcfRenderer implements ValueRenderer {
|
||||
write(currIndent);
|
||||
writeIdentifier(name);
|
||||
|
||||
if (value == null) { // unevaluated property
|
||||
write(" = ?");
|
||||
} else if (value instanceof Composite) {
|
||||
if (value instanceof Composite) {
|
||||
write(' ');
|
||||
visit(value);
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,9 @@ import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.msgpack.core.MessagePack;
|
||||
import org.msgpack.core.MessageUnpacker;
|
||||
import org.pkl.core.runtime.BaseModule;
|
||||
@@ -111,7 +113,7 @@ public class PklBinaryDecoder extends AbstractPklBinaryDecoder {
|
||||
|
||||
@Override
|
||||
protected Object doDecodeMap(MapDecodeIterator iter) {
|
||||
var map = CollectionUtils.newLinkedHashMap(iter.getSize());
|
||||
Map<@Nullable Object, @Nullable Object> map = CollectionUtils.newLinkedHashMap(iter.getSize());
|
||||
while (iter.hasNext()) {
|
||||
var entry = iter.next();
|
||||
map.put(entry.getFirst(), entry.getSecond());
|
||||
|
||||
@@ -54,6 +54,9 @@ final class PropertiesRenderer implements ValueRenderer {
|
||||
} else if (value instanceof Map<?, ?> map) {
|
||||
doVisitMap(null, map);
|
||||
} else if (value instanceof Pair<?, ?> pair) {
|
||||
// Pair coming from the runtime can never admit null (in-language null is represented as
|
||||
// PNull)
|
||||
//noinspection DataFlowIssue
|
||||
doVisitKeyAndValue(null, pair.getFirst(), pair.getSecond());
|
||||
} else {
|
||||
throw new RendererException(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,7 @@ package org.pkl.core;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import org.pkl.core.util.LateInit;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/** A type parameter of a generic class, type alias, or method. */
|
||||
public final class TypeParameter implements Serializable {
|
||||
@@ -27,7 +27,7 @@ public final class TypeParameter implements Serializable {
|
||||
private final String name;
|
||||
private final int index;
|
||||
|
||||
@LateInit private volatile Member owner;
|
||||
private volatile @Nullable Member owner;
|
||||
|
||||
public TypeParameter(Variance variance, String name, int index) {
|
||||
this.variance = variance;
|
||||
@@ -48,6 +48,7 @@ public final class TypeParameter implements Serializable {
|
||||
/** Returns the generic class, type alias, or method that this type parameter belongs to. */
|
||||
public Member getOwner() {
|
||||
assert owner != null;
|
||||
//noinspection DataFlowIssue
|
||||
return owner;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.pkl.core;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/**
|
||||
* A <a href="https://semver.org/spec/v2.0.0.html">semantic version</a>.
|
||||
@@ -59,7 +58,7 @@ public final class Version implements Comparable<Version> {
|
||||
private final @Nullable String preRelease;
|
||||
private final @Nullable String build;
|
||||
|
||||
@LateInit private volatile Identifier[] __preReleaseIdentifiers;
|
||||
private volatile Identifier @Nullable [] __preReleaseIdentifiers;
|
||||
|
||||
/** Constructs a semantic version. */
|
||||
public Version(
|
||||
@@ -230,6 +229,7 @@ public final class Version implements Comparable<Version> {
|
||||
: new Identifier(-1, str))
|
||||
.toArray(Identifier[]::new);
|
||||
}
|
||||
//noinspection DataFlowIssue
|
||||
return __preReleaseIdentifiers;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2025-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,19 +20,19 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.ExplodeLoop;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UInt8TypeAliasTypeNode;
|
||||
import org.pkl.core.ast.type.VmTypeMismatchException;
|
||||
import org.pkl.core.runtime.VmBytes;
|
||||
import org.pkl.core.runtime.VmUtils;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "Bytes()")
|
||||
public final class BytesLiteralNode extends ExpressionNode {
|
||||
@Children private final ExpressionNode[] elements;
|
||||
|
||||
@Child @LateInit private TypeNode typeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
|
||||
public BytesLiteralNode(SourceSection sourceSection, ExpressionNode[] elements) {
|
||||
super(sourceSection);
|
||||
|
||||
+3
-1
@@ -22,6 +22,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.DirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.ExplodeLoop;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.runtime.Identifier;
|
||||
import org.pkl.core.runtime.VmObjectLike;
|
||||
@@ -34,7 +35,7 @@ public abstract sealed class AbstractInvokeMethodLexicalNode extends ExpressionN
|
||||
protected final int levelsUp;
|
||||
private final boolean needsConst;
|
||||
@Children private ExpressionNode[] argumentNodes;
|
||||
@Child private DirectCallNode callNode;
|
||||
@Child private @Nullable DirectCallNode callNode;
|
||||
@CompilationFinal protected boolean isConstChecked;
|
||||
|
||||
protected AbstractInvokeMethodLexicalNode(
|
||||
@@ -90,6 +91,7 @@ public abstract sealed class AbstractInvokeMethodLexicalNode extends ExpressionN
|
||||
callNode = DirectCallNode.create(getCallTarget(owner));
|
||||
insert(callNode);
|
||||
}
|
||||
assert callNode != null;
|
||||
return callNode;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -19,17 +19,17 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/** Infers the parent to amend in `function createPerson(): Person = new { ... }`. */
|
||||
public final class InferParentWithinMethodNode extends ExpressionNode {
|
||||
private final VmLanguage language;
|
||||
private final Identifier methodName;
|
||||
@Child private ExpressionNode ownerNode;
|
||||
@CompilationFinal @LateInit private Object inferredParent;
|
||||
@Child private @Nullable ExpressionNode ownerNode;
|
||||
@CompilationFinal private @Nullable Object inferredParent;
|
||||
|
||||
public InferParentWithinMethodNode(
|
||||
SourceSection sourceSection,
|
||||
@@ -52,6 +52,7 @@ public final class InferParentWithinMethodNode extends ExpressionNode {
|
||||
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
assert ownerNode != null;
|
||||
var owner = (VmObjectLike) ownerNode.executeGeneric(frame);
|
||||
assert owner.isPrototype();
|
||||
|
||||
|
||||
+4
-3
@@ -19,6 +19,7 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.member.ObjectMethodNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
||||
@@ -26,14 +27,13 @@ import org.pkl.core.runtime.Identifier;
|
||||
import org.pkl.core.runtime.VmDynamic;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.runtime.VmObjectLike;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
/** Infers the parent to amend in `obj { local function createPerson(): Person = new { ... } }`. */
|
||||
public final class InferParentWithinObjectMethodNode extends ExpressionNode {
|
||||
private final VmLanguage language;
|
||||
private final Identifier localMethodName;
|
||||
@Child private ExpressionNode ownerNode;
|
||||
@CompilationFinal @LateInit private Object inferredParent;
|
||||
@Child private @Nullable ExpressionNode ownerNode;
|
||||
@CompilationFinal private @Nullable Object inferredParent;
|
||||
|
||||
public InferParentWithinObjectMethodNode(
|
||||
SourceSection sourceSection,
|
||||
@@ -58,6 +58,7 @@ public final class InferParentWithinObjectMethodNode extends ExpressionNode {
|
||||
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
assert ownerNode != null;
|
||||
var owner = (VmObjectLike) ownerNode.executeGeneric(frame);
|
||||
|
||||
var member = owner.getMember(localMethodName);
|
||||
|
||||
+3
-2
@@ -18,6 +18,7 @@ package org.pkl.core.ast.expression.member;
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.MemberLookupMode;
|
||||
import org.pkl.core.ast.expression.primary.GetEnclosingReceiverNode;
|
||||
@@ -49,8 +50,8 @@ public final class ReadAmbiguousLocalityPropertyNode extends ExpressionNode {
|
||||
private final Identifier name;
|
||||
private final int levelsUp;
|
||||
private final boolean needsConst;
|
||||
private @Child ExpressionNode readLocalPropertyNode;
|
||||
private @Child ExpressionNode readPropertyNode;
|
||||
@Child private @Nullable ExpressionNode readLocalPropertyNode;
|
||||
@Child private @Nullable ExpressionNode readPropertyNode;
|
||||
|
||||
public ReadAmbiguousLocalityPropertyNode(
|
||||
SourceSection sourceSection, Identifier name, int levelsUp, boolean needsConst) {
|
||||
|
||||
+4
-2
@@ -22,6 +22,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.DirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.ExplodeLoop;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
@@ -34,8 +35,8 @@ public final class ReadLocalPropertyNode extends ExpressionNode {
|
||||
private final Identifier name;
|
||||
private final int levelsUp;
|
||||
private final boolean needsConst;
|
||||
@Child private DirectCallNode callNode;
|
||||
@CompilationFinal private ObjectMember property;
|
||||
@Child private @Nullable DirectCallNode callNode;
|
||||
@CompilationFinal @Nullable private ObjectMember property;
|
||||
|
||||
public ReadLocalPropertyNode(
|
||||
SourceSection sourceSection, Identifier name, int levelsUp, boolean needsConst) {
|
||||
@@ -91,6 +92,7 @@ public final class ReadLocalPropertyNode extends ExpressionNode {
|
||||
callNode = DirectCallNode.create(property.getCallTarget());
|
||||
insert(callNode);
|
||||
}
|
||||
assert callNode != null;
|
||||
return callNode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.ast.member.SharedMemberNode;
|
||||
import org.pkl.core.externalreader.ExternalReaderProcessException;
|
||||
@@ -35,13 +36,12 @@ import org.pkl.core.runtime.VmMapping;
|
||||
import org.pkl.core.runtime.VmObjectBuilder;
|
||||
import org.pkl.core.util.GlobResolver;
|
||||
import org.pkl.core.util.GlobResolver.InvalidGlobPatternException;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "import*")
|
||||
public class ImportGlobNode extends AbstractImportNode {
|
||||
private final String globPattern;
|
||||
@Child @LateInit private SharedMemberNode memberNode;
|
||||
@CompilationFinal @LateInit private VmMapping cachedResult;
|
||||
@Child private @Nullable SharedMemberNode memberNode;
|
||||
@CompilationFinal private @Nullable VmMapping cachedResult;
|
||||
|
||||
public ImportGlobNode(
|
||||
SourceSection sourceSection,
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.net.URI;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.http.HttpClientException;
|
||||
import org.pkl.core.module.ResolvedModuleKey;
|
||||
@@ -28,13 +29,12 @@ import org.pkl.core.packages.PackageLoadError;
|
||||
import org.pkl.core.runtime.VmContext;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.runtime.VmTyped;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "import")
|
||||
public final class ImportNode extends AbstractImportNode {
|
||||
private final VmLanguage language;
|
||||
|
||||
@CompilationFinal @LateInit private VmTyped importedModule;
|
||||
@CompilationFinal private @Nullable VmTyped importedModule;
|
||||
|
||||
public ImportNode(
|
||||
VmLanguage language,
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.oracle.truffle.api.source.SourceSection;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import org.graalvm.collections.EconomicMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.ast.member.SharedMemberNode;
|
||||
import org.pkl.core.externalreader.ExternalReaderProcessException;
|
||||
@@ -36,12 +37,11 @@ import org.pkl.core.runtime.VmObjectBuilder;
|
||||
import org.pkl.core.util.GlobResolver;
|
||||
import org.pkl.core.util.GlobResolver.InvalidGlobPatternException;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "read*")
|
||||
public abstract class ReadGlobNode extends AbstractReadNode {
|
||||
private final EconomicMap<String, VmMapping> cachedResults = EconomicMap.create();
|
||||
@Child @LateInit private SharedMemberNode memberNode;
|
||||
@Child private @Nullable SharedMemberNode memberNode;
|
||||
|
||||
protected ReadGlobNode(SourceSection sourceSection, ModuleKey currentModule) {
|
||||
super(sourceSection, currentModule);
|
||||
@@ -67,6 +67,7 @@ public abstract class ReadGlobNode extends AbstractReadNode {
|
||||
@TruffleBoundary
|
||||
public Object read(String globPattern) {
|
||||
var cachedResult = cachedResults.get(globPattern);
|
||||
//noinspection ConstantValue
|
||||
if (cachedResult != null) return cachedResult;
|
||||
|
||||
// use same check as for globbed imports (see AstBuilder)
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.pkl.core.TypeParameter;
|
||||
import org.pkl.core.ast.VmModifier;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class ClassMethod extends ClassMember {
|
||||
private final List<TypeParameter> typeParameters;
|
||||
@@ -33,7 +34,7 @@ public final class ClassMethod extends ClassMember {
|
||||
// null = not deprecated, "" = no/empty message in the @Deprecated body
|
||||
private final @Nullable String deprecation;
|
||||
|
||||
@CompilationFinal private FunctionNode functionNode;
|
||||
@CompilationFinal @LateInit private FunctionNode functionNode;
|
||||
|
||||
public ClassMethod(
|
||||
SourceSection sourceSection,
|
||||
@@ -61,6 +62,7 @@ public final class ClassMethod extends ClassMember {
|
||||
}
|
||||
|
||||
public void initFunctionNode(FunctionNode functionNode) {
|
||||
//noinspection ConstantValue
|
||||
assert this.functionNode == null;
|
||||
this.functionNode = functionNode;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ public final class ClassNode extends ExpressionNode {
|
||||
// Caching of classes also guarantees that classes are singletons and can be compared by
|
||||
// identity,
|
||||
// which improves efficiency and performance (for example in shape checks).
|
||||
//noinspection ConstantValue
|
||||
if (cachedClass != null) return cachedClass;
|
||||
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.pkl.core.ast.member;
|
||||
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.PklRootNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
@@ -46,7 +45,7 @@ public final class ListingOrMappingTypeCastNode extends PklRootNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getName() {
|
||||
public String getName() {
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,11 @@ import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.UnresolvedTypeNode;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class LocalTypedPropertyNode extends RegularMemberNode {
|
||||
private final VmLanguage language;
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child @LateInit private TypeNode typeNode;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
private @Nullable Object defaultValue;
|
||||
private boolean defaultValueInitialized;
|
||||
|
||||
@@ -47,6 +46,7 @@ public final class LocalTypedPropertyNode extends RegularMemberNode {
|
||||
|
||||
public @Nullable Object getDefaultValue(VirtualFrame frame) {
|
||||
if (!defaultValueInitialized) {
|
||||
assert typeNode != null;
|
||||
defaultValue =
|
||||
typeNode.createDefaultValue(
|
||||
frame, language, member.getHeaderSection(), member.getQualifiedName());
|
||||
@@ -59,6 +59,7 @@ public final class LocalTypedPropertyNode extends RegularMemberNode {
|
||||
protected Object executeImpl(VirtualFrame frame) {
|
||||
if (typeNode == null) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
assert unresolvedTypeNode != null;
|
||||
typeNode = insert(unresolvedTypeNode.execute(frame));
|
||||
unresolvedTypeNode = null;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.UnresolvedTypeNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class ObjectMethodNode extends RegularMemberNode {
|
||||
private final VmLanguage language;
|
||||
@@ -33,7 +32,7 @@ public final class ObjectMethodNode extends RegularMemberNode {
|
||||
@Children private final @Nullable UnresolvedTypeNode[] unresolvedParameterTypeNodes;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedReturnTypeNode;
|
||||
|
||||
@CompilationFinal @LateInit private FunctionNode functionNode;
|
||||
@CompilationFinal private @Nullable FunctionNode functionNode;
|
||||
|
||||
public ObjectMethodNode(
|
||||
VmLanguage language,
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.util.LateInit;
|
||||
@@ -26,7 +27,7 @@ import org.pkl.core.util.LateInit;
|
||||
/** Resolves `<type>` to the type's default value in `new <type> { ... }`. */
|
||||
public final class GetParentForTypeNode extends ExpressionNode {
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private TypeNode typeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
private final String qualifiedName;
|
||||
|
||||
@CompilationFinal @LateInit Object defaultValue;
|
||||
@@ -49,6 +50,7 @@ public final class GetParentForTypeNode extends ExpressionNode {
|
||||
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) {
|
||||
//noinspection ConstantValue
|
||||
if (defaultValue != null) return defaultValue;
|
||||
CompilerDirectives.transferToInterpreterAndInvalidate();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,14 +19,14 @@ import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
@NodeInfo(shortName = "as")
|
||||
public final class TypeCastNode extends ExpressionNode {
|
||||
@Child private ExpressionNode valueNode;
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child @LateInit private TypeNode typeNode;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
|
||||
public TypeCastNode(
|
||||
SourceSection sourceSection,
|
||||
@@ -43,6 +43,7 @@ public final class TypeCastNode extends ExpressionNode {
|
||||
// don't compile unresolvedTypeNode.execute()
|
||||
// invalidation is done by insert()
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
assert unresolvedTypeNode != null;
|
||||
typeNode = insert(unresolvedTypeNode.execute(frame));
|
||||
unresolvedTypeNode = null;
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ public abstract class TypeNode extends PklNode {
|
||||
public abstract static class FrameSlotTypeNode extends TypeNode {
|
||||
@CompilationFinal protected int slot = -1;
|
||||
|
||||
@CompilationFinal @Child protected WriteFrameSlotNode writeFrameSlotNode;
|
||||
@CompilationFinal @Child protected @Nullable WriteFrameSlotNode writeFrameSlotNode;
|
||||
|
||||
protected FrameSlotTypeNode(SourceSection sourceSection) {
|
||||
super(sourceSection);
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.pkl.core.runtime.VmLanguage;
|
||||
@NodeInfo(shortName = "is")
|
||||
public final class TypeTestNode extends ExpressionNode {
|
||||
@Child private ExpressionNode valueNode;
|
||||
@Child private UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable UnresolvedTypeNode unresolvedTypeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
|
||||
public TypeTestNode(
|
||||
@@ -49,6 +49,7 @@ public final class TypeTestNode extends ExpressionNode {
|
||||
// don't compile unresolvedTypeNode.execute()
|
||||
// invalidation is done by insert()
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
assert unresolvedTypeNode != null;
|
||||
typeNode = insert(unresolvedTypeNode.execute(frame));
|
||||
unresolvedTypeNode = null;
|
||||
}
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ final class ExternalResourceResolverImpl implements ExternalResourceResolver {
|
||||
readResponses.computeIfAbsent(
|
||||
baseUri,
|
||||
(uri) -> {
|
||||
var future = new CompletableFuture<byte[]>();
|
||||
var future = new CompletableFuture<byte @Nullable []>();
|
||||
var request =
|
||||
new ReadResourceRequest(requestIdGenerator.nextLong(), evaluatorId, uri);
|
||||
try {
|
||||
|
||||
@@ -46,7 +46,6 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import org.pkl.core.SecurityManagerException;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
import org.pkl.core.util.Exceptions;
|
||||
|
||||
@@ -93,7 +92,7 @@ final class JdkHttpClient implements HttpClient {
|
||||
HttpRequest request,
|
||||
BodyHandler<T> responseBodyHandler,
|
||||
HttpRequestChecker httpRequestChecker)
|
||||
throws IOException, SecurityManagerException {
|
||||
throws IOException {
|
||||
try {
|
||||
return underlying.send(request, responseBodyHandler);
|
||||
} catch (ConnectException e) {
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class Messages {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -93,12 +93,14 @@ public class PathElement {
|
||||
}
|
||||
|
||||
/** Returns the element at path {@code basePath}, given a {@link Path}. */
|
||||
@SuppressWarnings("DataFlowIssue") // incorrect analysis; this can return null.
|
||||
public @Nullable TreePathElement getElement(Path basePath) {
|
||||
var path = basePath.normalize();
|
||||
var element = this;
|
||||
for (var i = 0; i < path.getNameCount(); i++) {
|
||||
var part = path.getName(i).toString();
|
||||
element = element.getChildren().get(part);
|
||||
//noinspection ConstantValue
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ public final class ProjectDependenciesManager {
|
||||
public Map<String, Dependency> getLocalPackageDependencies(PackageUri packageUri) {
|
||||
ensureDependenciesInitialized();
|
||||
var dep = localPackageDependencies.get(packageUri);
|
||||
//noinspection ConstantValue
|
||||
assert dep != null;
|
||||
return dep;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public abstract class Dependency {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public abstract class Dependency {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -217,6 +217,7 @@ public final class DependencyMetadata {
|
||||
var map = new HashMap<>();
|
||||
for (var kv : value) {
|
||||
var kvObj = (JsObject) kv;
|
||||
assert kvObj != null;
|
||||
map.put(parsePObject(kvObj.get("key")), parsePObject(kvObj.get("value")));
|
||||
}
|
||||
return map;
|
||||
@@ -294,7 +295,7 @@ public final class DependencyMetadata {
|
||||
var ret = new ArrayList<String>(arr.size());
|
||||
for (var elem : arr) {
|
||||
if (!(elem instanceof String string)) {
|
||||
throw new FormatException("string", elem.getClass());
|
||||
throw new FormatException("string", elem != null ? elem.getClass() : Void.class);
|
||||
}
|
||||
ret.add(string);
|
||||
}
|
||||
@@ -414,7 +415,7 @@ public final class DependencyMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@@ -624,8 +625,8 @@ public final class DependencyMetadata {
|
||||
jsonWriter.endObject();
|
||||
}
|
||||
|
||||
private void writeGenericObject(Object value) throws IOException {
|
||||
if (value instanceof PNull) {
|
||||
private void writeGenericObject(@Nullable Object value) throws IOException {
|
||||
if (value == null || value instanceof PNull) {
|
||||
jsonWriter.nullValue();
|
||||
} else if (value instanceof PObject pObject) {
|
||||
writePObject(pObject);
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.pkl.core.packages;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.Version;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
@@ -98,7 +99,7 @@ public final class PackageAssetUri {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public final class PackageUri {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ package org.pkl.core.project;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.packages.PackageUri;
|
||||
import org.pkl.core.util.ErrorMessages;
|
||||
@@ -84,7 +85,7 @@ public record CanonicalPackageUri(URI baseUri, int majorVersion) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ public final class Project {
|
||||
sb.append("\n│");
|
||||
}
|
||||
sb.append("\n│ ");
|
||||
sb.append(uri.toString());
|
||||
sb.append(uri);
|
||||
}
|
||||
sb.append("\n└─");
|
||||
}
|
||||
@@ -477,7 +477,7 @@ public final class Project {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
@@ -611,7 +611,7 @@ public final class Project {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ public final class ProjectDependenciesResolver {
|
||||
private void updateDependency(Dependency dependency) {
|
||||
var canonicalPackageUri = CanonicalPackageUri.fromPackageUri(dependency.getPackageUri());
|
||||
var currentDependency = resolvedDependencies.get(canonicalPackageUri);
|
||||
//noinspection ConstantValue
|
||||
if (currentDependency == null
|
||||
|| currentDependency.getVersion().compareTo(dependency.getVersion()) < 0) {
|
||||
EconomicMaps.put(resolvedDependencies, canonicalPackageUri, dependency);
|
||||
|
||||
@@ -135,6 +135,7 @@ public final class ProjectDeps {
|
||||
}
|
||||
|
||||
/** Given a declared dependency, return the resolved dependency. */
|
||||
@SuppressWarnings("DataFlowIssue") // incorrect analysis
|
||||
public @Nullable Dependency get(CanonicalPackageUri canonicalPackageUri) {
|
||||
return resolvedDependencies.get(canonicalPackageUri);
|
||||
}
|
||||
@@ -150,7 +151,7 @@ public final class ProjectDeps {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ public final class FileSystemManager {
|
||||
|
||||
public static synchronized FileSystem getFileSystem(URI uri) throws IOException {
|
||||
var fs = fileSystems.get(uri);
|
||||
// incorrect nullability for `org.graalvm.collections.UnmodifiableEconomicMap`
|
||||
//noinspection ConstantValue
|
||||
if (fs != null) {
|
||||
var count = counts.get(fs);
|
||||
assert count != null;
|
||||
|
||||
@@ -40,10 +40,10 @@ public final class ModuleInfo {
|
||||
|
||||
@LateInit private List<VmTyped> annotations;
|
||||
|
||||
@LateInit private VmTyped __mirror;
|
||||
private @Nullable VmTyped __mirror;
|
||||
private final Object mirrorLock = new Object();
|
||||
|
||||
@LateInit private ModuleSchema __moduleSchema;
|
||||
private @Nullable ModuleSchema __moduleSchema;
|
||||
private final Object moduleSchemaLock = new Object();
|
||||
|
||||
public ModuleInfo(
|
||||
@@ -65,12 +65,12 @@ public final class ModuleInfo {
|
||||
}
|
||||
|
||||
public void initAnnotations(List<VmTyped> annotations) {
|
||||
//noinspection ConstantValue
|
||||
assert this.annotations == null;
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
public List<VmTyped> getAnnotations() {
|
||||
assert annotations != null;
|
||||
return annotations;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,8 +101,14 @@ public final class StackTraceRenderer {
|
||||
if (hint != null) {
|
||||
out.append(AnsiTheme.ERROR_MESSAGE_HINT, hint);
|
||||
} else {
|
||||
assert hintBuilder != null;
|
||||
out.append(AnsiTheme.ERROR_MESSAGE_HINT, () -> hintBuilder.accept(out, true));
|
||||
out.append(
|
||||
AnsiTheme.ERROR_MESSAGE_HINT,
|
||||
() -> {
|
||||
// nullaway needs this assertion
|
||||
//noinspection ConstantValue
|
||||
assert hintBuilder != null;
|
||||
hintBuilder.accept(out, true);
|
||||
});
|
||||
}
|
||||
out.append('\n');
|
||||
}
|
||||
|
||||
@@ -491,11 +491,11 @@ public final class TestRunner {
|
||||
sb.append("\n Expected: ");
|
||||
appendLocation(sb, expectedLocation);
|
||||
sb.append("\n ");
|
||||
sb.append(AnsiTheme.TEST_EXAMPLE_OUTPUT, expectedValue.replaceAll("\n", "\n "));
|
||||
sb.append(AnsiTheme.TEST_EXAMPLE_OUTPUT, expectedValue.replace("\n", "\n "));
|
||||
sb.append("\n Actual: ");
|
||||
appendLocation(sb, actualLocation);
|
||||
sb.append("\n ");
|
||||
sb.append(AnsiTheme.TEST_EXAMPLE_OUTPUT, actualValue.replaceAll("\n", "\n "));
|
||||
sb.append(AnsiTheme.TEST_EXAMPLE_OUTPUT, actualValue.replace("\n", "\n "));
|
||||
});
|
||||
return new Failure("Example Failure", sb.toString());
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ public final class VmContext {
|
||||
}
|
||||
|
||||
public void initialize(Holder holder) {
|
||||
//noinspection ConstantValue
|
||||
assert this.holder == null;
|
||||
this.holder = holder;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.frame.MaterializedFrame;
|
||||
import java.util.Objects;
|
||||
import org.graalvm.collections.UnmodifiableEconomicMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.PClassInfo;
|
||||
import org.pkl.core.PObject;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
@@ -75,12 +76,14 @@ public final class VmDynamic extends VmObject {
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public PObject export() {
|
||||
assert forced : "Value was not forced prior to export";
|
||||
|
||||
var properties =
|
||||
CollectionUtils.<String, Object>newLinkedHashMap(EconomicMaps.size(cachedValues));
|
||||
|
||||
iterateMemberValues(
|
||||
iterateAlreadyForcedMemberValues(
|
||||
(key, member, value) -> {
|
||||
properties.put(key.toString(), VmValue.exportNullable(value));
|
||||
properties.put(key.toString(), VmValue.export(value));
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -99,9 +102,8 @@ public final class VmDynamic extends VmObject {
|
||||
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) // noinspection Contract
|
||||
return true;
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof VmDynamic other)) return false;
|
||||
|
||||
// could use shallow force, but deep force is cached
|
||||
@@ -115,6 +117,7 @@ public final class VmDynamic extends VmObject {
|
||||
if (isHiddenOrLocalProperty(key)) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
//noinspection ConstantValue
|
||||
assert value != null;
|
||||
var otherValue = other.getCachedValue(key);
|
||||
if (!value.equals(otherValue)) return false;
|
||||
@@ -137,6 +140,7 @@ public final class VmDynamic extends VmObject {
|
||||
if (isHiddenOrLocalProperty(key)) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
//noinspection ConstantValue
|
||||
assert value != null;
|
||||
result += key.hashCode() ^ value.hashCode();
|
||||
}
|
||||
|
||||
@@ -87,13 +87,15 @@ public final class VmListing extends VmListingOrMapping {
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public List<Object> export() {
|
||||
assert forced : "Value was not forced prior to export";
|
||||
|
||||
var properties = new ArrayList<>(EconomicMaps.size(cachedValues));
|
||||
|
||||
iterateMemberValues(
|
||||
iterateAlreadyForcedMemberValues(
|
||||
(key, prop, value) -> {
|
||||
if (isDefaultProperty(key)) return true;
|
||||
|
||||
properties.add(VmValue.exportNullable(value));
|
||||
properties.add(VmValue.export(value));
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -127,6 +129,7 @@ public final class VmListing extends VmListingOrMapping {
|
||||
if (key instanceof Identifier) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
//noinspection ConstantValue
|
||||
assert value != null;
|
||||
var otherValue = other.getCachedValue(key);
|
||||
if (!value.equals(otherValue)) return false;
|
||||
@@ -149,6 +152,7 @@ public final class VmListing extends VmListingOrMapping {
|
||||
if (key instanceof Identifier) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
//noinspection ConstantValue
|
||||
assert value != null;
|
||||
result = 31 * result + value.hashCode();
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ public final class VmMap extends VmValue implements Iterable<Map.Entry<Object, O
|
||||
|
||||
for (var key : other.keyOrder) {
|
||||
var value = other.map.get(key);
|
||||
assert value != null;
|
||||
|
||||
if (!map.containsKey(key)) {
|
||||
keyOrderBuilder.append(key);
|
||||
|
||||
@@ -21,19 +21,18 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import org.graalvm.collections.UnmodifiableEconomicMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.member.ListingOrMappingTypeCastNode;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
import org.pkl.core.util.CollectionUtils;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.LateInit;
|
||||
import org.pkl.core.util.MutableLong;
|
||||
|
||||
public final class VmMapping extends VmListingOrMapping {
|
||||
private long cachedLength = -1;
|
||||
|
||||
@GuardedBy("this")
|
||||
@LateInit
|
||||
private VmSet __allKeys;
|
||||
private @Nullable VmSet __allKeys;
|
||||
|
||||
private static final class EmptyHolder {
|
||||
private static final VmMapping EMPTY =
|
||||
@@ -94,13 +93,15 @@ public final class VmMapping extends VmListingOrMapping {
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public Map<Object, Object> export() {
|
||||
assert forced : "Value was not forced prior to export";
|
||||
|
||||
var properties = CollectionUtils.newLinkedHashMap(EconomicMaps.size(cachedValues));
|
||||
|
||||
iterateMemberValues(
|
||||
iterateAlreadyForcedMemberValues(
|
||||
(key, prop, value) -> {
|
||||
if (isDefaultProperty(key)) return true;
|
||||
|
||||
properties.put(VmValue.export(key), VmValue.exportNullable(value));
|
||||
properties.put(VmValue.export(key), VmValue.export(value));
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -119,9 +120,8 @@ public final class VmMapping extends VmListingOrMapping {
|
||||
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) // noinspection Contract
|
||||
return true;
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof VmMapping other)) return false;
|
||||
|
||||
// could use shallow force, but deep force is cached
|
||||
@@ -135,6 +135,7 @@ public final class VmMapping extends VmListingOrMapping {
|
||||
if (key instanceof Identifier) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
//noinspection ConstantValue
|
||||
assert value != null;
|
||||
var otherValue = other.getCachedValue(key);
|
||||
if (!value.equals(otherValue)) return false;
|
||||
@@ -157,6 +158,7 @@ public final class VmMapping extends VmListingOrMapping {
|
||||
if (key instanceof Identifier) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
//noinspection ConstantValue
|
||||
assert value != null;
|
||||
result += key.hashCode() ^ value.hashCode();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public abstract class VmObject extends VmObjectLike {
|
||||
protected final EconomicMap<Object, Object> cachedValues;
|
||||
|
||||
protected int cachedHash;
|
||||
private boolean forced;
|
||||
protected boolean forced;
|
||||
|
||||
public VmObject(
|
||||
MaterializedFrame enclosingFrame,
|
||||
@@ -204,17 +204,20 @@ public abstract class VmObject extends VmObjectLike {
|
||||
|
||||
/**
|
||||
* Exports this object's members. Skips local members, hidden members, class definitions, and type
|
||||
* aliases. Members that haven't been forced have a `null` value.
|
||||
* aliases.
|
||||
*
|
||||
* <p>Assumes that this object has already been forced.
|
||||
*/
|
||||
@TruffleBoundary
|
||||
protected final Map<String, Object> exportMembers() {
|
||||
var result = CollectionUtils.<String, Object>newLinkedHashMap(EconomicMaps.size(cachedValues));
|
||||
Map<String, Object> result = CollectionUtils.newLinkedHashMap(EconomicMaps.size(cachedValues));
|
||||
assert forced : "Value was not forced prior to export";
|
||||
|
||||
iterateMemberValues(
|
||||
iterateAlreadyForcedMemberValues(
|
||||
(key, member, value) -> {
|
||||
if (member.isClass() || member.isTypeAlias()) return true;
|
||||
|
||||
result.put(key.toString(), VmValue.exportNullable(value));
|
||||
result.put(key.toString(), VmValue.export(value));
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.pkl.core.Composite;
|
||||
import org.pkl.core.PClass;
|
||||
import org.pkl.core.PClassInfo;
|
||||
import org.pkl.core.PType;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.Reference;
|
||||
import org.pkl.core.TypeAlias;
|
||||
import org.pkl.core.util.paguro.RrbTree;
|
||||
@@ -218,6 +219,15 @@ public final class VmReference extends VmValue {
|
||||
normalizeTypes(prop.getType(), clazz.getPClass().getModuleClass(), result);
|
||||
}
|
||||
|
||||
private static PClassInfo<?> getClassInfo(Object value) {
|
||||
if (value instanceof VmValue vmValue) return vmValue.getVmClass().getPClassInfo();
|
||||
if (value instanceof String) return PClassInfo.String;
|
||||
if (value instanceof Boolean) return PClassInfo.Boolean;
|
||||
if (value instanceof Long) return PClassInfo.Int;
|
||||
if (value instanceof Double) return PClassInfo.Float;
|
||||
throw new PklBugException("Not a Pkl value: " + value.getClass());
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
private static void getCandidateSubscriptType(PType type, Object key, Set<PType> result) {
|
||||
if (type == PType.UNKNOWN) {
|
||||
@@ -244,8 +254,7 @@ public final class VmReference extends VmValue {
|
||||
var keyTypes = normalizeTypes(typeArgs.get(0), clazz.getPClass().getModuleClass());
|
||||
for (var kt : iterateTypes(keyTypes)) {
|
||||
if (kt == PType.UNKNOWN
|
||||
|| (kt instanceof PType.Class klazz
|
||||
&& klazz.getPClass().getInfo() == PClassInfo.forValue(VmValue.export(key)))
|
||||
|| (kt instanceof PType.Class klazz && klazz.getPClass().getInfo() == getClassInfo(key))
|
||||
|| (kt instanceof PType.StringLiteral stringLiteral
|
||||
&& stringLiteral.getLiteral().equals(key))) {
|
||||
normalizeTypes(typeArgs.get(1), clazz.getPClass().getModuleClass(), result);
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.ast.type.TypeNode.ConstrainedTypeNode;
|
||||
import org.pkl.core.ast.type.TypeNode.TypeVariableNode;
|
||||
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class VmTypeAlias extends VmValue {
|
||||
private final SourceSection sourceSection;
|
||||
@@ -48,17 +47,15 @@ public final class VmTypeAlias extends VmValue {
|
||||
private final List<TypeParameter> typeParameters;
|
||||
private final MaterializedFrame enclosingFrame;
|
||||
|
||||
@LateInit private TypeNode typeNode;
|
||||
private @Nullable TypeNode typeNode;
|
||||
|
||||
@LateInit
|
||||
@GuardedBy("pTypeAliasLock")
|
||||
private TypeAlias __pTypeAlias;
|
||||
private @Nullable TypeAlias __pTypeAlias;
|
||||
|
||||
private final Object pTypeAliasLock = new Object();
|
||||
|
||||
@LateInit
|
||||
@GuardedBy("mirrorLock")
|
||||
private VmTyped __mirror;
|
||||
private @Nullable VmTyped __mirror;
|
||||
|
||||
private final Object mirrorLock = new Object();
|
||||
|
||||
@@ -86,7 +83,6 @@ public final class VmTypeAlias extends VmValue {
|
||||
}
|
||||
|
||||
public void initTypeCheckNode(TypeNode typeNode) {
|
||||
assert this.typeNode == null;
|
||||
this.typeNode = typeNode;
|
||||
}
|
||||
|
||||
@@ -100,6 +96,7 @@ public final class VmTypeAlias extends VmValue {
|
||||
*/
|
||||
@TruffleBoundary
|
||||
public SourceSection getBaseTypeSection() {
|
||||
assert typeNode != null;
|
||||
if (typeNode instanceof ConstrainedTypeNode constrainedTypeNode) {
|
||||
return constrainedTypeNode.getBaseTypeSection();
|
||||
}
|
||||
@@ -116,6 +113,7 @@ public final class VmTypeAlias extends VmValue {
|
||||
*/
|
||||
@TruffleBoundary
|
||||
public SourceSection getConstraintSection() {
|
||||
assert typeNode != null;
|
||||
if (typeNode instanceof ConstrainedTypeNode) {
|
||||
return ((ConstrainedTypeNode) typeNode).getFirstConstraintSection();
|
||||
}
|
||||
@@ -169,6 +167,7 @@ public final class VmTypeAlias extends VmValue {
|
||||
}
|
||||
|
||||
public TypeNode getTypeNode() {
|
||||
assert typeNode != null;
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
@@ -178,6 +177,7 @@ public final class VmTypeAlias extends VmValue {
|
||||
|
||||
@TruffleBoundary
|
||||
public TypeNode instantiate(TypeNode[] typeArgumentNodes) {
|
||||
assert typeNode != null;
|
||||
// Cloning the type node means that the entire type check remains within a single root node,
|
||||
// which should be good for interpreted and compiled performance alike:
|
||||
// * Fewer root nodes to call
|
||||
@@ -265,6 +265,7 @@ public final class VmTypeAlias extends VmValue {
|
||||
}
|
||||
|
||||
public VmTyped getTypeMirror() {
|
||||
assert typeNode != null;
|
||||
return typeNode.getMirror();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,9 @@ import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.expression.unary.ImportNode;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class VmTyped extends VmObject {
|
||||
@CompilationFinal @LateInit private VmClass clazz;
|
||||
@CompilationFinal private @Nullable VmClass clazz;
|
||||
|
||||
public VmTyped(
|
||||
MaterializedFrame enclosingFrame,
|
||||
@@ -162,6 +161,8 @@ public final class VmTyped extends VmObject {
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public Composite export() {
|
||||
assert forced : "Value was not forced prior to export";
|
||||
assert clazz != null;
|
||||
if (!isModuleObject()) {
|
||||
return new PObject(clazz.getPClassInfo(), exportMembers());
|
||||
}
|
||||
@@ -190,6 +191,7 @@ public final class VmTyped extends VmObject {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof VmTyped other)) return false;
|
||||
|
||||
assert clazz != null;
|
||||
if (clazz != other.clazz) return false;
|
||||
// could use shallow force, but deep force is cached
|
||||
force(false);
|
||||
@@ -210,6 +212,7 @@ public final class VmTyped extends VmObject {
|
||||
public int hashCode() {
|
||||
if (cachedHash != 0) return cachedHash;
|
||||
|
||||
assert clazz != null;
|
||||
force(false);
|
||||
var result = 0;
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ public final class VmObjectFactory<E> {
|
||||
? TypeCheckedPropertyNodeGen.create(null, new FrameDescriptor(), member, bodyNode)
|
||||
: new UntypedObjectMemberNode(null, new FrameDescriptor(), member, bodyNode);
|
||||
member.initMemberNode(node);
|
||||
//noinspection ConstantValue
|
||||
if (members.put(identifier, member) != null) {
|
||||
throw new VmExceptionBuilder()
|
||||
.bug(
|
||||
@@ -110,7 +111,6 @@ public final class VmObjectFactory<E> {
|
||||
@TruffleBoundary
|
||||
public VmTyped create(@Nullable E extraStorage) {
|
||||
var clazz = classSupplier.get();
|
||||
assert clazz != null;
|
||||
|
||||
var result =
|
||||
new VmTyped(VmUtils.createEmptyMaterializedFrame(), clazz.getPrototype(), clazz, members);
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.pkl.core.stdlib.ExternalPropertyNode;
|
||||
* CLI args) would lead to incorrect behavior, as a single base module instance is shared across all
|
||||
* language contexts, and properties (whether external or not) are evaluated just once.
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
@SuppressWarnings("unused")
|
||||
public final class BaseNodes {
|
||||
private BaseNodes() {}
|
||||
|
||||
@@ -64,6 +64,7 @@ public final class BaseNodes {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public abstract static class Regex extends ExternalMethod1Node {
|
||||
// cache Regex object to avoid repeated java.util.Pattern.compile()
|
||||
@Specialization(guards = "pattern.equals(cachedPattern)")
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.LoopNode;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.ast.expression.binary.*;
|
||||
import org.pkl.core.ast.internal.IsInstanceOfNode;
|
||||
import org.pkl.core.ast.internal.IsInstanceOfNodeGen;
|
||||
@@ -33,7 +34,6 @@ import org.pkl.core.stdlib.base.CollectionNodes.CompareByNode;
|
||||
import org.pkl.core.stdlib.base.CollectionNodes.CompareNode;
|
||||
import org.pkl.core.stdlib.base.CollectionNodes.CompareWithNode;
|
||||
import org.pkl.core.util.EconomicSets;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
// duplication between ListNodes and SetNodes is "intentional"
|
||||
// (sharing nodes between VmCollection subtypes results in
|
||||
@@ -1336,7 +1336,7 @@ public final class ListNodes {
|
||||
|
||||
public abstract static class toBytes extends ExternalMethod0Node {
|
||||
|
||||
@Child @LateInit private TypeNode typeNode;
|
||||
@Child private @Nullable TypeNode typeNode;
|
||||
|
||||
private TypeNode getTypeNode() {
|
||||
if (typeNode == null) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.pkl.core.runtime.*;
|
||||
import org.pkl.core.stdlib.ExternalMethod1Node;
|
||||
import org.pkl.core.stdlib.PklConverter;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.LateInit;
|
||||
import org.pkl.core.util.json.JsonHandler;
|
||||
import org.pkl.core.util.json.JsonParser;
|
||||
import org.pkl.core.util.json.ParseException;
|
||||
@@ -71,6 +72,8 @@ public final class ParserNodes {
|
||||
|
||||
private final Deque<Object> currPath = new ArrayDeque<>();
|
||||
|
||||
@LateInit private Object value;
|
||||
|
||||
public Handler(PklConverter converter, boolean useMapping) {
|
||||
this.converter = converter;
|
||||
this.useMapping = useMapping;
|
||||
@@ -78,8 +81,6 @@ public final class ParserNodes {
|
||||
currPath.push(VmValueConverter.TOP_LEVEL_VALUE);
|
||||
}
|
||||
|
||||
private Object value;
|
||||
|
||||
@Override
|
||||
public void endNull() {
|
||||
value = VmNull.withoutDefault();
|
||||
|
||||
@@ -617,7 +617,7 @@ public final class RendererNodes {
|
||||
// - All element types are resolved also.
|
||||
// - All string literal types are combined into a single String case.
|
||||
var hasString = false;
|
||||
var elements = new ArrayList<TypeNode>();
|
||||
var elements = new ArrayList<@Nullable TypeNode>();
|
||||
for (var t : ((UnionTypeNode) type).getElementTypeNodes()) {
|
||||
var resolved = resolveType(t);
|
||||
if (resolved instanceof StringLiteralTypeNode || resolved instanceof StringTypeNode) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import org.graalvm.collections.EconomicMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.pkl.core.TestResults;
|
||||
import org.pkl.core.TestResults.Error;
|
||||
import org.pkl.core.TestResults.TestResult;
|
||||
@@ -59,8 +60,6 @@ public final class JUnitReporter implements TestReporter {
|
||||
var totalTests = allTestResults.stream().mapToLong(TestResults::totalTests).sum();
|
||||
var totalFailures = allTestResults.stream().mapToLong(TestResults::totalFailures).sum();
|
||||
|
||||
assert aggregateSuiteName != null;
|
||||
|
||||
var attrs =
|
||||
buildAttributes(
|
||||
"name", aggregateSuiteName,
|
||||
@@ -206,12 +205,15 @@ public final class JUnitReporter implements TestReporter {
|
||||
members.size() - 4);
|
||||
}
|
||||
|
||||
private VmMapping buildAttributes(Object... attributes) {
|
||||
private VmMapping buildAttributes(@Nullable Object... attributes) {
|
||||
EconomicMap<Object, ObjectMember> attrs = EconomicMaps.create(attributes.length);
|
||||
for (int i = 0; i < attributes.length; i += 2) {
|
||||
attrs.put(
|
||||
attributes[i],
|
||||
VmUtils.createSyntheticObjectEntry(attributes[i].toString(), attributes[i + 1]));
|
||||
for (var i = 0; i < attributes.length; i += 2) {
|
||||
var key = attributes[i];
|
||||
var value = attributes[i + 1];
|
||||
if (key == null || value == null) {
|
||||
continue;
|
||||
}
|
||||
attrs.put(key, VmUtils.createSyntheticObjectEntry(key.toString(), value));
|
||||
}
|
||||
return new VmMapping(
|
||||
VmUtils.createEmptyMaterializedFrame(), BaseModule.getMappingClass().getPrototype(), attrs);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.pkl.core.util;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public final class CollectionUtils {
|
||||
private static final float LOAD_FACTOR = 0.75f;
|
||||
@@ -45,7 +46,8 @@ public final class CollectionUtils {
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(int expectedSize) {
|
||||
public static <K extends @Nullable Object, V extends @Nullable Object>
|
||||
LinkedHashMap<K, V> newLinkedHashMap(int expectedSize) {
|
||||
return new LinkedHashMap<>((int) (expectedSize / LOAD_FACTOR) + 1, LOAD_FACTOR);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,11 +81,13 @@ public final class EconomicMaps {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@TruffleBoundary
|
||||
public static <K, V> @Nullable V get(UnmodifiableEconomicMap<K, V> self, K key) {
|
||||
return self.get(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
@TruffleBoundary
|
||||
public static <K, V> @Nullable V get(UnmodifiableEconomicMap<K, V> self, K key, V defaultValue) {
|
||||
return self.get(key, defaultValue);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -381,6 +381,7 @@ public final class JsonParser {
|
||||
}
|
||||
|
||||
private void startCapture() {
|
||||
//noinspection ConstantValue
|
||||
if (captureBuffer == null) {
|
||||
captureBuffer = new StringBuilder();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jspecify.annotations.Nullable;
|
||||
/**
|
||||
* Writes a JSON (<a href="http://www.ietf.org/rfc/rfc7159.txt">RFC 7159</a>) encoded value to a
|
||||
* stream, one token at a time. The stream includes both literal values (strings, numbers, booleans
|
||||
* and nulls) as well as the begin and end delimiters of objects and arrays.
|
||||
* and nulls) as well as the beginning and ending delimiters of objects and arrays.
|
||||
*
|
||||
* <h3>Encoding JSON</h3>
|
||||
*
|
||||
@@ -195,7 +195,7 @@ public final class JsonWriter implements Closeable, Flushable {
|
||||
|
||||
/**
|
||||
* Sets the indentation string to be repeated for each level of indentation in the encoded
|
||||
* document. If {@code indent.isEmpty()} the encoded document will be compact. Otherwise the
|
||||
* document. If {@code indent.isEmpty()} the encoded document will be compact. Otherwise, the
|
||||
* encoded document will be more human-readable.
|
||||
*
|
||||
* @param indent a string containing only whitespace.
|
||||
@@ -418,6 +418,8 @@ public final class JsonWriter implements Closeable, Flushable {
|
||||
public JsonWriter value(boolean value) throws IOException {
|
||||
writeDeferredName();
|
||||
beforeValue();
|
||||
// avoid method dispatch
|
||||
//noinspection SimplifiableConditionalExpression
|
||||
out.write(value ? "true" : "false");
|
||||
return this;
|
||||
}
|
||||
@@ -433,6 +435,8 @@ public final class JsonWriter implements Closeable, Flushable {
|
||||
}
|
||||
writeDeferredName();
|
||||
beforeValue();
|
||||
// avoid method dispatch
|
||||
//noinspection SimplifiableConditionalExpression
|
||||
out.write(value ? "true" : "false");
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -922,7 +922,10 @@ public abstract class RrbTree<E> implements BaseList<E>, Indented {
|
||||
/** {@inheritDoc} */
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user