use of com.intellij.openapi.command.WriteCommandAction in project android by JetBrains.
the class OverrideResourceAction method createValueResource.
private static void createValueResource(@NotNull final Project project, @NotNull final PsiDirectory resDir, @NotNull PsiFile file, @NotNull PsiDirectory resourceSubdir, @NotNull final String resName, @NotNull final String value, @NotNull final ResourceType type, @NotNull final String oldTagText, boolean open) {
final String filename = file.getName();
final List<String> dirNames = Collections.singletonList(resourceSubdir.getName());
final AtomicReference<PsiElement> openAfter = new AtomicReference<PsiElement>();
final WriteCommandAction<Void> action = new WriteCommandAction<Void>(project, "Override Resource " + resName, file) {
@Override
protected void run(@NotNull Result<Void> result) {
List<ResourceElement> elements = Lists.newArrayListWithExpectedSize(1);
// AndroidResourceUtil.createValueResource will create a new resource value in the given resource
// folder (and record the corresponding tags added in the elements list passed into it).
// However, it only creates a new element and sets the name attribute on it; it does not
// transfer attributes, child content etc. Therefore, we use this utility method first to
// create the corresponding tag, and then *afterwards* we will replace the tag with a text copy
// from the resource tag we are overriding. We do this all under a single write lock such
// that it becomes a single atomic operation.
AndroidResourceUtil.createValueResource(project, resDir.getVirtualFile(), resName, type, filename, dirNames, value, elements);
if (elements.size() == 1) {
final XmlTag tag = elements.get(0).getXmlTag();
if (tag != null && tag.isValid()) {
try {
XmlTag tagFromText = XmlElementFactory.getInstance(tag.getProject()).createTagFromText(oldTagText);
PsiElement replaced = tag.replace(tagFromText);
openAfter.set(replaced);
} catch (IncorrectOperationException e) {
// The user tried to override an invalid XML fragment: don't attempt to do a replacement in that case
openAfter.set(tag);
}
}
}
}
};
action.execute();
PsiElement tag = openAfter.get();
if (open && tag != null) {
NavigationUtil.openFileWithPsiElement(tag, true, true);
}
}
use of com.intellij.openapi.command.WriteCommandAction in project android by JetBrains.
the class OverrideResourceAction method forkResourceFile.
private static void forkResourceFile(@NotNull Project project, @NotNull final ResourceFolderType folderType, @NotNull final VirtualFile file, @Nullable final XmlFile xmlFile, @Nullable String myNewFolder, @Nullable Configuration configuration, boolean open) {
final FolderConfiguration folderConfig;
if (myNewFolder == null) {
// Open a file chooser to select the configuration to be created
VirtualFile parentFolder = file.getParent();
assert parentFolder != null;
VirtualFile res = parentFolder.getParent();
folderConfig = selectFolderConfig(project, res, folderType);
} else {
folderConfig = FolderConfiguration.getConfigForFolder(myNewFolder);
}
if (folderConfig == null) {
return;
}
final Computable<Pair<String, VirtualFile>> computable = new Computable<Pair<String, VirtualFile>>() {
@Override
public Pair<String, VirtualFile> compute() {
String folderName = folderConfig.getFolderName(folderType);
try {
VirtualFile parentFolder = file.getParent();
assert parentFolder != null;
VirtualFile res = parentFolder.getParent();
VirtualFile newParentFolder = res.findChild(folderName);
if (newParentFolder == null) {
newParentFolder = res.createChildDirectory(this, folderName);
if (newParentFolder == null) {
String message = String.format("Could not create folder %1$s in %2$s", folderName, res.getPath());
return Pair.of(message, null);
}
}
final VirtualFile existing = newParentFolder.findChild(file.getName());
if (existing != null && existing.exists()) {
String message = String.format("File 'res/%1$s/%2$s' already exists!", folderName, file.getName());
return Pair.of(message, null);
}
// Attempt to get the document from the PSI file rather than the file on disk: get edited contents too
String text;
if (xmlFile != null) {
text = xmlFile.getText();
} else {
text = StreamUtil.readText(file.getInputStream(), "UTF-8");
}
VirtualFile newFile = newParentFolder.createChildData(this, file.getName());
VfsUtil.saveText(newFile, text);
return Pair.of(null, newFile);
} catch (IOException e2) {
String message = String.format("Failed to create File 'res/%1$s/%2$s' : %3$s", folderName, file.getName(), e2.getMessage());
return Pair.of(message, null);
}
}
};
WriteCommandAction<Pair<String, VirtualFile>> action = new WriteCommandAction<Pair<String, VirtualFile>>(project, "Add Resource") {
@Override
protected void run(@NotNull Result<Pair<String, VirtualFile>> result) throws Throwable {
result.setResult(computable.compute());
}
};
Pair<String, VirtualFile> result = action.execute().getResultObject();
String error = result.getFirst();
VirtualFile newFile = result.getSecond();
if (error != null) {
Messages.showErrorDialog(project, error, "Create Resource");
} else {
// First create a compatible configuration based on the current configuration
if (configuration != null) {
ConfigurationManager configurationManager = configuration.getConfigurationManager();
configurationManager.createSimilar(newFile, file);
}
if (open) {
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, newFile, -1);
FileEditorManager.getInstance(project).openEditor(descriptor, true);
}
}
}
use of com.intellij.openapi.command.WriteCommandAction in project android by JetBrains.
the class InferSupportAnnotationsAction method checkModules.
// For Android we need to check SDK version and possibly update the gradle project file
protected boolean checkModules(@NotNull Project project, @NotNull AnalysisScope scope, @NotNull Map<Module, PsiFile> modules) {
Set<Module> modulesWithoutAnnotations = new HashSet<>();
Set<Module> modulesWithLowVersion = new HashSet<>();
for (Module module : modules.keySet()) {
AndroidModuleInfo info = AndroidModuleInfo.get(module);
if (info != null && info.getBuildSdkVersion() != null && info.getBuildSdkVersion().getFeatureLevel() < MIN_SDK_WITH_NULLABLE) {
modulesWithLowVersion.add(module);
}
GradleBuildModel buildModel = GradleBuildModel.get(module);
if (buildModel == null) {
Logger.getInstance(InferSupportAnnotationsAction.class).warn("Unable to find Gradle build model for module " + module.getModuleFilePath());
continue;
}
boolean dependencyFound = false;
DependenciesModel dependenciesModel = buildModel.dependencies();
if (dependenciesModel != null) {
for (ArtifactDependencyModel dependency : dependenciesModel.artifacts(COMPILE)) {
String notation = dependency.compactNotation().value();
if (notation.startsWith(SdkConstants.APPCOMPAT_LIB_ARTIFACT) || notation.startsWith(SdkConstants.SUPPORT_LIB_ARTIFACT) || notation.startsWith(SdkConstants.ANNOTATIONS_LIB_ARTIFACT)) {
dependencyFound = true;
break;
}
}
}
if (!dependencyFound) {
modulesWithoutAnnotations.add(module);
}
}
if (!modulesWithLowVersion.isEmpty()) {
Messages.showErrorDialog(project, String.format("Infer Support Annotations requires the project sdk level be set to %1$d or greater.", MIN_SDK_WITH_NULLABLE), "Infer Support Annotations");
return false;
}
if (modulesWithoutAnnotations.isEmpty()) {
return true;
}
String moduleNames = StringUtil.join(modulesWithoutAnnotations, Module::getName, ", ");
int count = modulesWithoutAnnotations.size();
String message = String.format("The %1$s %2$s %3$sn't refer to the existing '%4$s' library with Android nullity annotations. \n\n" + "Would you like to add the %5$s now?", pluralize("module", count), moduleNames, count > 1 ? "do" : "does", SupportLibrary.SUPPORT_ANNOTATIONS.getArtifactId(), pluralize("dependency", count));
if (Messages.showOkCancelDialog(project, message, "Infer Nullity Annotations", Messages.getErrorIcon()) == Messages.OK) {
LocalHistoryAction action = LocalHistory.getInstance().startAction(ADD_DEPENDENCY);
try {
new WriteCommandAction(project, ADD_DEPENDENCY) {
@Override
protected void run(@NotNull Result result) throws Throwable {
RepositoryUrlManager manager = RepositoryUrlManager.get();
String annotationsLibraryCoordinate = manager.getLibraryStringCoordinate(SupportLibrary.SUPPORT_ANNOTATIONS, true);
for (Module module : modulesWithoutAnnotations) {
addDependency(module, annotationsLibraryCoordinate);
}
GradleSyncInvoker.Request request = new GradleSyncInvoker.Request().setGenerateSourcesOnSuccess(false);
GradleSyncInvoker.getInstance().requestProjectSync(project, request, new GradleSyncListener.Adapter() {
@Override
public void syncSucceeded(@NotNull Project project) {
restartAnalysis(project, scope);
}
});
}
}.execute();
} finally {
action.finish();
}
}
return false;
}
use of com.intellij.openapi.command.WriteCommandAction in project android by JetBrains.
the class HtmlLinkManager method handleNewClassUrl.
private static void handleNewClassUrl(@NotNull String url, @NotNull Module module) {
assert url.startsWith(URL_CREATE_CLASS) : url;
String s = url.substring(URL_CREATE_CLASS.length());
final Project project = module.getProject();
String title = "Create Custom View";
final String className;
final String packageName;
int index = s.lastIndexOf('.');
if (index == -1) {
className = s;
packageName = MergedManifest.get(module).getPackage();
if (packageName == null) {
return;
}
} else {
packageName = s.substring(0, index);
className = s.substring(index + 1);
}
CreateClassDialog dialog = new CreateClassDialog(project, title, className, packageName, CreateClassKind.CLASS, true, module) {
@Override
protected boolean reportBaseInSourceSelectionInTest() {
return true;
}
};
dialog.show();
if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
final PsiDirectory targetDirectory = dialog.getTargetDirectory();
if (targetDirectory != null) {
PsiClass newClass = new WriteCommandAction<PsiClass>(project, "Create Class") {
@Override
protected void run(@NotNull Result<PsiClass> result) throws Throwable {
PsiClass targetClass = JavaDirectoryService.getInstance().createClass(targetDirectory, className);
PsiManager manager = PsiManager.getInstance(project);
final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
final PsiElementFactory factory = facade.getElementFactory();
// Extend android.view.View
PsiJavaCodeReferenceElement superclassReference = factory.createReferenceElementByFQClassName(CLASS_VIEW, targetClass.getResolveScope());
PsiReferenceList extendsList = targetClass.getExtendsList();
if (extendsList != null) {
extendsList.add(superclassReference);
}
// Add constructor
GlobalSearchScope scope = GlobalSearchScope.allScope(project);
PsiJavaFile javaFile = (PsiJavaFile) targetClass.getContainingFile();
PsiImportList importList = javaFile.getImportList();
if (importList != null) {
PsiClass contextClass = JavaPsiFacade.getInstance(project).findClass(CLASS_CONTEXT, scope);
if (contextClass != null) {
importList.add(factory.createImportStatement(contextClass));
}
PsiClass attributeSetClass = JavaPsiFacade.getInstance(project).findClass(CLASS_ATTRIBUTE_SET, scope);
if (attributeSetClass != null) {
importList.add(factory.createImportStatement(attributeSetClass));
}
}
PsiMethod constructor = factory.createMethodFromText("public " + className + "(Context context, AttributeSet attrs, int defStyle) {\n" + " super(context, attrs, defStyle);\n" + "}\n", targetClass);
targetClass.add(constructor);
// Format class
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject());
PsiFile containingFile = targetClass.getContainingFile();
if (containingFile != null) {
codeStyleManager.reformat(javaFile);
}
result.setResult(targetClass);
}
}.execute().getResultObject();
if (newClass != null) {
PsiFile file = newClass.getContainingFile();
if (file != null) {
openEditor(project, file, newClass.getTextOffset());
}
}
}
}
}
use of com.intellij.openapi.command.WriteCommandAction in project android by JetBrains.
the class HtmlLinkManager method assignLayout.
private static void assignLayout(@NotNull final Project project, @NotNull final XmlFile file, @NotNull final String activityName, @NotNull final String layout) {
WriteCommandAction<Void> action = new WriteCommandAction<Void>(project, "Assign Preview Layout", file) {
@Override
protected void run(@NotNull Result<Void> result) throws Throwable {
AndroidResourceUtil.ensureNamespaceImported(file, TOOLS_URI, null);
Collection<XmlTag> xmlTags = PsiTreeUtil.findChildrenOfType(file, XmlTag.class);
for (XmlTag tag : xmlTags) {
if (tag.getName().equals(VIEW_FRAGMENT)) {
String name = tag.getAttributeValue(ATTR_CLASS);
if (name == null || name.isEmpty()) {
name = tag.getAttributeValue(ATTR_NAME, ANDROID_URI);
}
if (activityName.equals(name)) {
tag.setAttribute(ATTR_LAYOUT, TOOLS_URI, layout);
}
}
}
}
};
action.execute();
}
Aggregations