mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
external storage: do not store bytecode taget level in the project files
This commit is contained in:
@@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.impl.ExternalModuleListStorage;
|
||||
import com.intellij.openapi.project.ModuleListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
@@ -60,6 +61,8 @@ import org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfig
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.compiler.ExternalCompilerConfigurationStorageKt.*;
|
||||
import static com.intellij.util.JdomKt.element;
|
||||
import static org.jetbrains.jps.model.java.impl.compiler.ResourcePatterns.normalizeWildcards;
|
||||
import static org.jetbrains.jps.model.java.impl.compiler.ResourcePatterns.optimize;
|
||||
import static org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfigurationSerializer.DEFAULT_WILDCARD_PATTERNS;
|
||||
@@ -153,7 +156,6 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
|
||||
@Override
|
||||
public Element getState() {
|
||||
|
||||
Element state = new Element("state");
|
||||
XmlSerializer.serializeInto(myState, state, new SkipDefaultValuesSerializationFilters() {
|
||||
@Override
|
||||
@@ -207,30 +209,17 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
state.addContent(annotationProcessingSettings);
|
||||
}
|
||||
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !myModuleBytecodeTarget.isEmpty()) {
|
||||
final Element bytecodeTarget = addChild(state, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
|
||||
List<String> moduleNames = getFilteredModuleNameList(myProject, myModuleBytecodeTarget, false);
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !moduleNames.isEmpty()) {
|
||||
final Element bytecodeTarget = element(state, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
|
||||
if (!StringUtil.isEmpty(myBytecodeTargetLevel)) {
|
||||
bytecodeTarget.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, myBytecodeTargetLevel);
|
||||
}
|
||||
if (!myModuleBytecodeTarget.isEmpty()) {
|
||||
final List<String> moduleNames = new ArrayList<>(myModuleBytecodeTarget.keySet());
|
||||
Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER);
|
||||
for (String name : moduleNames) {
|
||||
final Element moduleElement = addChild(bytecodeTarget, JpsJavaCompilerConfigurationSerializer.MODULE);
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name);
|
||||
final String value = myModuleBytecodeTarget.get(name);
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, value != null ? value : "");
|
||||
}
|
||||
}
|
||||
writeBytecodeTarget(moduleNames, myModuleBytecodeTarget, bytecodeTarget);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(Element state) {
|
||||
readExternal(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBuildProcessHeapSize(final int javacPreferredHeapSize) {
|
||||
final int heapSize = myState.BUILD_PROCESS_HEAP_SIZE;
|
||||
@@ -702,8 +691,8 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void readExternal(@NotNull Element parentNode) {
|
||||
@Override
|
||||
public void loadState(@NotNull Element parentNode) {
|
||||
myState = XmlSerializer.deserialize(parentNode, State.class);
|
||||
if (!myProject.isDefault()) {
|
||||
for (Element option : parentNode.getChildren("option")) {
|
||||
@@ -785,20 +774,16 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
|
||||
myBytecodeTargetLevel = null;
|
||||
myModuleBytecodeTarget.clear();
|
||||
final Element bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
|
||||
|
||||
Element bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
|
||||
if (bytecodeTargetElement != null) {
|
||||
myBytecodeTargetLevel = bytecodeTargetElement.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE);
|
||||
for (Element elem : bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) {
|
||||
final String name = elem.getAttributeValue(JpsJavaCompilerConfigurationSerializer.NAME);
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
final String target = elem.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE);
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
myModuleBytecodeTarget.put(name, target);
|
||||
}
|
||||
readByteTargetLevel(parentNode);
|
||||
}
|
||||
|
||||
Map<String, String> externalState = myProject.getComponent(ExternalCompilerConfigurationStorage.class).getLoadedState();
|
||||
if (externalState != null) {
|
||||
myModuleBytecodeTarget.putAll(externalState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.compiler
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import com.intellij.openapi.components.State
|
||||
import com.intellij.openapi.components.Storage
|
||||
import com.intellij.openapi.module.impl.ModuleManagerImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.isExternalStorageEnabled
|
||||
import com.intellij.openapi.roots.ExternalProjectSystemRegistry
|
||||
import com.intellij.openapi.roots.ProjectModelElement
|
||||
import com.intellij.openapi.roots.ProjectModelExternalSource
|
||||
import com.intellij.util.element
|
||||
import gnu.trove.THashMap
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfigurationSerializer
|
||||
import java.util.*
|
||||
|
||||
@State(name = "ExternalCompilerConfigurationStorage", storages = arrayOf(Storage("compiler.xml")), externalStorageOnly = true)
|
||||
internal class ExternalCompilerConfigurationStorage(private val project: Project) : PersistentStateComponent<Element>, ProjectModelElement {
|
||||
var loadedState: Map<String, String>? = null
|
||||
private set
|
||||
|
||||
override fun getState(): Element {
|
||||
val e = Element("state")
|
||||
if (!project.isExternalStorageEnabled) {
|
||||
return e
|
||||
}
|
||||
|
||||
val map = (CompilerConfigurationImpl.getInstance(project) as CompilerConfigurationImpl).modulesBytecodeTargetMap
|
||||
val moduleNames = getFilteredModuleNameList(project, map, true)
|
||||
if (moduleNames.isNotEmpty()) {
|
||||
writeBytecodeTarget(moduleNames, map, e.element(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL))
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
override fun loadState(state: Element) {
|
||||
loadedState = readByteTargetLevel(state)
|
||||
}
|
||||
|
||||
override fun getExternalSource(): ProjectModelExternalSource? {
|
||||
val externalProjectSystemRegistry = ExternalProjectSystemRegistry.getInstance()
|
||||
for (module in ModuleManagerImpl.getInstanceImpl(project).modules) {
|
||||
externalProjectSystemRegistry.getExternalSource(module)?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getFilteredModuleNameList(project: Project, map: Map<String, String>, isExternal: Boolean): List<String> {
|
||||
if (!project.isExternalStorageEnabled) {
|
||||
return map.keys.toList()
|
||||
}
|
||||
|
||||
val moduleManager = ModuleManagerImpl.getInstanceImpl(project)
|
||||
val externalProjectSystemRegistry = ExternalProjectSystemRegistry.getInstance()
|
||||
return map.keys.filter {
|
||||
// if no module and !isExternal - return true because CompilerConfigurationImpl saves module name as is without module existence check and this logic is preserved
|
||||
val module = moduleManager.findModuleByName(it) ?: return@filter !isExternal
|
||||
(externalProjectSystemRegistry.getExternalSource(module) != null) == isExternal
|
||||
}
|
||||
}
|
||||
|
||||
internal fun writeBytecodeTarget(moduleNames: List<String>, map: Map<String, String>, element: Element) {
|
||||
Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER)
|
||||
for (name in moduleNames) {
|
||||
val moduleElement = element.element(JpsJavaCompilerConfigurationSerializer.MODULE)
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name)
|
||||
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, map.get(name) ?: "")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun readByteTargetLevel(parentNode: Element): Map<String, String> {
|
||||
val result = THashMap<String, String>()
|
||||
val bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL) ?: return result
|
||||
for (element in bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) {
|
||||
val name = element.getAttributeValue(JpsJavaCompilerConfigurationSerializer.NAME) ?: continue
|
||||
val target = element.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE) ?: continue
|
||||
result.put(name, target)
|
||||
}
|
||||
return result
|
||||
}
|
||||
+7
-16
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.jps.model.serialization;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -57,7 +43,7 @@ public abstract class JpsLoaderBase {
|
||||
String fileName = serializer.getConfigFileName();
|
||||
Path configFile = fileName == null ? defaultConfigFile : dir.resolve(fileName);
|
||||
Runnable timingLog = TimingLog.startActivity("loading: " + configFile.getFileName() + ":" + serializer.getComponentName());
|
||||
Element componentTag = JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName());
|
||||
Element componentTag = loadComponentData(serializer, configFile);
|
||||
if (componentTag != null) {
|
||||
serializer.loadExtension(element, componentTag);
|
||||
}
|
||||
@@ -67,6 +53,11 @@ public abstract class JpsLoaderBase {
|
||||
timingLog.run();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <E extends JpsElement> Element loadComponentData(@NotNull JpsElementExtensionSerializerBase<E> serializer, Path configFile) {
|
||||
return JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null if file doesn't exist
|
||||
*/
|
||||
|
||||
+6
@@ -110,6 +110,12 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
return dir.getParent().getFileName().toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Element loadRootElement(@NotNull Path file) {
|
||||
return super.loadRootElement(file);
|
||||
}
|
||||
|
||||
private void loadFromDirectory(@NotNull Path dir) {
|
||||
myProject.setName(getDirectoryBaseProjectName(dir));
|
||||
Path defaultConfigFile = dir.resolve("misc.xml");
|
||||
|
||||
@@ -36,7 +36,7 @@ private open class ModuleStoreImpl(module: Module, private val pathMacroManager:
|
||||
override fun <T> getStorageSpecs(component: PersistentStateComponent<T>, stateSpec: State, operation: StateStorageOperation): List<Storage> {
|
||||
val result = super.getStorageSpecs(component, stateSpec, operation)
|
||||
return StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny {
|
||||
LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager.componentManager!!, result, operation) }
|
||||
LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager.componentManager!!, stateSpec, result, operation) }
|
||||
} ?: result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ abstract class ProjectStoreBase(override final val project: ProjectImpl) : Compo
|
||||
else {
|
||||
result!!.sortWith(deprecatedComparator)
|
||||
StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny {
|
||||
LOG.runAndLogException { it.customizeStorageSpecs(component, project, result!!, operation) }
|
||||
LOG.runAndLogException { it.customizeStorageSpecs(component, project, stateSpec, result!!, operation) }
|
||||
}?.let {
|
||||
// yes, DEPRECATED_PROJECT_FILE_STORAGE_ANNOTATION is not added in this case
|
||||
return it
|
||||
|
||||
@@ -174,7 +174,14 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
key = normalizedCollapsedPath
|
||||
}
|
||||
else {
|
||||
key = storageClass.name!!
|
||||
val storageClassName = storageClass.name!!
|
||||
// we cannot change this ancient logic for now, so, detect this case manually
|
||||
if (storageClassName === "com.intellij.openapi.externalSystem.configurationStore.ExternalProjectStorage") {
|
||||
key = "$normalizedCollapsedPath@ExternalProjectStorage"
|
||||
}
|
||||
else {
|
||||
key = storageClassName
|
||||
}
|
||||
}
|
||||
|
||||
val storage = storageLock.read { storages.get(key) } ?: return storageLock.write {
|
||||
|
||||
+1
-6
@@ -33,12 +33,7 @@ internal open class ExternalProjectStorage(fileSpec: String, project: Project, s
|
||||
|
||||
override fun createSaveSession(states: StateMap) = object : XmlElementStorageSaveSession<ExternalProjectStorage>(states, this) {
|
||||
override fun saveLocally(element: Element?) {
|
||||
if (element == null) {
|
||||
manager.fileStorage.remove(fileSpec)
|
||||
}
|
||||
else {
|
||||
manager.fileStorage.write(fileSpec, element)
|
||||
}
|
||||
manager.fileStorage.write(fileSpec, element)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -63,7 +63,7 @@ internal class ExternalSystemStreamProviderFactory(private val project: Project)
|
||||
})
|
||||
}
|
||||
|
||||
override fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, storages: List<Storage>, operation: StateStorageOperation): List<Storage>? {
|
||||
override fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, stateSpec: State, storages: List<Storage>, operation: StateStorageOperation): List<Storage>? {
|
||||
val project = componentManager as? Project ?: (componentManager as Module).project
|
||||
// we store isExternalStorageEnabled option in the project workspace file, so, for such components external storage is always disabled and not applicable
|
||||
if ((storages.size == 1 && storages.first().value == StoragePathMacros.WORKSPACE_FILE) || !project.isExternalStorageEnabled) {
|
||||
@@ -94,14 +94,21 @@ internal class ExternalSystemStreamProviderFactory(private val project: Project)
|
||||
// so, we just add our storage as first and default storages in the end as fallback
|
||||
|
||||
// on write default storages also returned, because default FileBasedStorage will remove data if component has external source
|
||||
|
||||
val result = ArrayList<Storage>(storages.size + 1)
|
||||
val annotation: FileStorageAnnotation
|
||||
if (componentManager is Project) {
|
||||
result.add(FileStorageAnnotation(storages.get(0).value, false, ExternalProjectStorage::class.java))
|
||||
val fileSpec = storages.get(0).value
|
||||
annotation = FileStorageAnnotation(fileSpec, false, ExternalProjectStorage::class.java)
|
||||
}
|
||||
else {
|
||||
result.add(EXTERNAL_MODULE_STORAGE_ANNOTATION)
|
||||
annotation = EXTERNAL_MODULE_STORAGE_ANNOTATION
|
||||
}
|
||||
|
||||
if (stateSpec.externalStorageOnly) {
|
||||
return listOf(annotation)
|
||||
}
|
||||
|
||||
val result = ArrayList<Storage>(storages.size + 1)
|
||||
result.add(annotation)
|
||||
result.addAll(storages)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.components;
|
||||
|
||||
import com.intellij.openapi.util.Getter;
|
||||
@@ -60,6 +46,11 @@ public @interface State {
|
||||
|
||||
Class<? extends NameGetter> presentableName() default NameGetter.class;
|
||||
|
||||
/**
|
||||
* Is this component intended to store data only in the external storage.
|
||||
*/
|
||||
boolean externalStorageOnly() default false;
|
||||
|
||||
abstract class NameGetter implements Getter<String> {
|
||||
}
|
||||
}
|
||||
|
||||
+3
-20
@@ -1,24 +1,7 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.components.ComponentManager
|
||||
import com.intellij.openapi.components.PersistentStateComponent
|
||||
import com.intellij.openapi.components.StateStorageOperation
|
||||
import com.intellij.openapi.components.Storage
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
|
||||
/**
|
||||
@@ -38,5 +21,5 @@ interface StreamProviderFactory {
|
||||
* `storages` are preprocessed by component store - not raw from state spec.
|
||||
* @return null if not applicable
|
||||
*/
|
||||
fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, storages: List<Storage>, operation: StateStorageOperation): List<Storage>? = null
|
||||
fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, stateSpec: State, storages: List<Storage>, operation: StateStorageOperation): List<Storage>? = null
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ import com.intellij.openapi.roots.ProjectModelElement
|
||||
import com.intellij.openapi.roots.ProjectModelExternalSource
|
||||
import org.jdom.Element
|
||||
|
||||
@State(name = "ExternalModuleListStorage", storages = arrayOf(Storage("modules.xml")))
|
||||
@State(name = "ExternalModuleListStorage", storages = arrayOf(Storage("modules.xml")), externalStorageOnly = true)
|
||||
internal class ExternalModuleListStorage(private val project: Project) : PersistentStateComponent<Element>, ProjectModelElement {
|
||||
var loadedState: Set<ModulePath>? = null
|
||||
private set
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
<interface-class>com.intellij.packaging.artifacts.ArtifactManager</interface-class>
|
||||
<implementation-class>com.intellij.packaging.impl.artifacts.ArtifactManagerImpl</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>com.intellij.compiler.ExternalCompilerConfigurationStorage</implementation-class>
|
||||
<loadForDefaultProject/>
|
||||
</component>
|
||||
<component>
|
||||
<interface-class>com.intellij.compiler.CompilerConfiguration</interface-class>
|
||||
<implementation-class>com.intellij.compiler.CompilerConfigurationImpl</implementation-class>
|
||||
|
||||
Reference in New Issue
Block a user