# HG changeset patch # User Michael Van De Vanter # Date 1440198616 25200 # Node ID 04b13488da2a76d7923405a71c6ae3b052b31702 # Parent ce5495c70de4ab970b2867bd58f489d38ac3df8f Truffle/Source: modify behavior of factory Source.fromFileName((CharSequence, String). If a Source already exists with this file name, and it was created with this method originally, then the original Source will be returned with contents replaced. diff -r ce5495c70de4 -r 04b13488da2a truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Fri Aug 21 11:17:40 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Fri Aug 21 16:10:16 2015 -0700 @@ -151,18 +151,29 @@ } /** - * Gets the canonical representation of a source file, whose contents have already been read and - * need not be read again. It is confirmed that the file resolves to a file name, so it can be - * indexed by canonical path. It is not confirmed that the text supplied agrees with the file's - * contents or even whether the file is readable. + * Gets the canonical representation of a source file whose contents are the responsibility of + * the client: + * * - * @param chars textual source code already read from the file + * @param chars textual source code already read from the file, must not be null * @param fileName * @return canonical representation of the file's contents. - * @throws IOException if the file cannot be found + * @throws IOException if the file cannot be found, or if an existing Source not created by this + * method matches the file name */ public static Source fromFileName(CharSequence chars, String fileName) throws IOException { CompilerAsserts.neverPartOfCompilation(); + assert chars != null; final WeakReference nameRef = nameToSource.get(fileName); Source source = nameRef == null ? null : nameRef.get(); @@ -173,9 +184,15 @@ final WeakReference pathRef = nameToSource.get(path); source = pathRef == null ? null : pathRef.get(); if (source == null) { - source = new FileSource(file, fileName, path, chars); + source = new ClientManagedFileSource(file, fileName, path, chars); nameToSource.put(path, new WeakReference<>(source)); } + } else if (source instanceof ClientManagedFileSource) { + final ClientManagedFileSource modifiableSource = (ClientManagedFileSource) source; + modifiableSource.setCode(chars); + return modifiableSource; + } else { + throw new IOException("Attempt to modify contents of a file Source"); } return source; } @@ -749,16 +766,9 @@ private long timeStamp; // timestamp of the cache in the file system public FileSource(File file, String name, String path) { - this(file, name, path, null); - } - - public FileSource(File file, String name, String path, CharSequence chars) { this.file = file.getAbsoluteFile(); this.name = name; this.path = path; - if (chars != null) { - this.code = chars.toString(); - } } @Override @@ -843,6 +853,83 @@ } } + // TODO (mlvdv) if we keep this, hoist a superclass in common with FileSource. + private static final class ClientManagedFileSource extends Source { + + private final File file; + private final String name; // Name used originally to describe the source + private final String path; // Normalized path description of an actual file + private String code; // The file's contents, as provided by the client + + public ClientManagedFileSource(File file, String name, String path, CharSequence chars) { + this.file = file.getAbsoluteFile(); + this.name = name; + this.path = path; + setCode(chars); + } + + void setCode(CharSequence chars) { + this.code = chars.toString(); + } + + @Override + public String getName() { + return name; + } + + @Override + public String getShortName() { + return file.getName(); + } + + @Override + Object getHashKey() { + return path; + } + + @Override + public String getCode() { + return code; + } + + @Override + public String getPath() { + return path; + } + + @Override + public URL getURL() { + return null; + } + + @Override + public Reader getReader() { + return new StringReader(code); + } + + @Override + public int hashCode() { + return path.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ClientManagedFileSource) { + ClientManagedFileSource other = (ClientManagedFileSource) obj; + return path.equals(other.path); + } + return false; + } + + @Override + void reset() { + this.code = null; + } + } + private static final class URLSource extends Source { private static final Map> urlToSource = new HashMap<>();