/* * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
void initialize() {
isAttemptingCorral = false;
dependenciesNeeded = false;
toRedefine = null; // assure NPE if classToLoad not called
activeGuts = si.guts();
markOldDeclarationOverwritten();
}
// Set the outer wrap of our Snippet void setWrap(Collection<Unit> exceptUnit, Collection<Unit> plusUnfiltered) { if (isImport()) {
si.setOuterWrap(state.outerMap.wrapImport(activeGuts, si));
} else { // Collect Units for be wrapped together. Just this except for overloaded methods
List<Unit> units; if (snippet().kind() == Kind.METHOD) {
String name = ((MethodSnippet) snippet()).name();
units = plusUnfiltered.stream()
.filter(u -> u.snippet().kind() == Kind.METHOD &&
((MethodSnippet) u.snippet()).name().equals(name))
.toList();
} else {
units = Collections.singletonList(this);
} // Keys to exclude from imports
Set<Key> except = exceptUnit.stream()
.map(u -> u.snippet().key())
.collect(toSet()); // Snippets to add to imports
Collection<Snippet> plus = plusUnfiltered.stream()
.filter(u -> !units.contains(u))
.map(Unit::snippet)
.toList(); // Snippets to wrap in an outer
List<Snippet> snippets = units.stream()
.map(Unit::snippet)
.toList(); // Snippet wraps to wrap in an outer
List<Wrap> wraps = units.stream()
.map(u -> u.activeGuts)
.toList(); // Set the outer wrap for this snippet
si.setOuterWrap(state.outerMap.wrapInClass(except, plus, snippets, wraps));
state.debug(DBG_WRAP, "++setWrap() %s\n%s\n",
si, si.outerWrap().wrapped());
}
}
privateboolean isRecoverable() { // Unit failed, use corralling if it is defined on this Snippet, // and either all the errors are resolution errors or this is a // redeclare of an existing method return compilationDiagnostics.hasErrors()
&& si instanceof DeclarationSnippet
&& (isDependency()
|| (si.subKind() != SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND
&& compilationDiagnostics.hasResolutionErrorsAndNoOthers()));
}
/** * If it meets the conditions for corralling, install the corralled wrap * @return true is the corralled wrap was installed
*/ boolean corralIfNeeded(Collection<Unit> working) { if (isRecoverable()
&& si.corralled() != null) {
activeGuts = si.corralled();
setWrap(working, working); return isAttemptingCorral = true;
} return isAttemptingCorral = false;
}
/** * Process the class information from the last compile. Requires loading of * returned list. * * @return the list of classes to load
*/
Stream<ClassBytecodes> classesToLoad(List<String> classnames) {
toRedefine = new ArrayList<>();
List<ClassBytecodes> toLoad = new ArrayList<>(); if (status.isDefined() && !isImport()) { // Classes should only be loaded/redefined if the compile left them // in a defined state. Imports do not have code and are not loaded. for (String cn : classnames) {
ClassInfo ci = state.classTracker.get(cn); if (ci.isLoaded()) { if (ci.isCurrent()) { // nothing to do
} else {
toRedefine.add(ci);
}
} else { // If not loaded, add to the list of classes to load.
toLoad.add(ci.toClassBytecodes());
dependenciesNeeded = true;
}
}
} return toLoad.stream();
}
/** * Redefine classes needing redefine. classesToLoad() must be called first. * * @return true if all redefines succeeded (can be vacuously true)
*/ boolean doRedefines() { if (toRedefine.isEmpty()) { returntrue;
}
ClassBytecodes[] cbcs = toRedefine.stream()
.map(ClassInfo::toClassBytecodes)
.toArray(ClassBytecodes[]::new); try {
state.executionControl().redefine(cbcs);
state.classTracker.markLoaded(cbcs); returntrue;
} catch (ClassInstallException ex) {
state.classTracker.markLoaded(cbcs, ex.installed()); returnfalse;
} catch (EngineTerminationException ex) {
state.closeDown(); returnfalse;
} catch (NotImplementedException ex) { returnfalse;
}
}
void markForReplacement() { // increment for replace class wrapper
si.setSequenceNumber(++seq);
}
privatevoid checkForOverwrite(AnalyzeTask at) {
secondaryEvents = new ArrayList<>(); if (replaceOldEvent != null) secondaryEvents.add(replaceOldEvent);
// Defined methods can overwrite methods of other (equivalent) snippets if (si.kind() == Kind.METHOD && status.isDefined()) {
MethodSnippet msi = (MethodSnippet) si;
msi.setQualifiedParameterTypes(
computeQualifiedParameterTypes(at, msi));
Status overwrittenStatus = overwriteMatchingMethod(msi); if (overwrittenStatus != null) {
prevStatus = overwrittenStatus;
signatureChanged = true;
}
}
}
// Check if there is a method whose user-declared parameter types are // different (and thus has a different snippet) but whose compiled parameter // types are the same. if so, consider it an overwrite replacement. private Status overwriteMatchingMethod(MethodSnippet msi) {
String qpt = msi.qualifiedParameterTypes();
List<MethodSnippet> matching = state.methods()
.filter(sn ->
sn != null
&& sn != msi
&& sn.status().isActive()
&& sn.name().equals(msi.name())
&& qpt.equals(sn.qualifiedParameterTypes()))
.toList();
// Look through all methods for a method of the same name, with the // same computed qualified parameter types
Status overwrittenStatus = null; for (MethodSnippet sn : matching) {
overwrittenStatus = sn.status();
SnippetEvent se = new SnippetEvent(
sn, overwrittenStatus, OVERWRITTEN, false, msi, null, null);
sn.setOverwritten();
secondaryEvents.add(se);
state.debug(DBG_EVNT, "Overwrite event #%d -- key: %s before: %s status: %s sig: %b cause: %s\n",
secondaryEvents.size(), se.snippet(), se.previousStatus(),
se.status(), se.isSignatureChange(), se.causeSnippet());
} return overwrittenStatus;
}
// Extract the parameter type string from the method signature, // if method did not compile use the user-supplied parameter types return paren >= 0
? signature.substring(0, paren + 1)
: msi.parameterTypes();
}
/** * Separate out the unresolvedDependencies errors from both the other * corralling errors and the overall errors.
*/ privatestaticclass UnresolvedExtractor {
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.