void (@NotNull final Module module, @NotNull final VirtualFile formFile, @Nullable final GuiEditor editor, @NotNull final IRootContainer rootContainer, @Nullable final ProgressIndicator progress) { if (module.isDisposed()) { return; } // 1. Validate class to bind final String classToBind = rootContainer.getClassToBind(); final PsiClass psiClass; if (classToBind != null) { psiClass = FormEditingUtil.findClassToBind(module, classToBind); if (psiClass == null) { final QuickFix[] fixes = editor != null ? new QuickFix[]{new CreateClassToBindFix(editor, classToBind)} : QuickFix.EMPTY_ARRAY; final ErrorInfo errorInfo = new ErrorInfo(null, null, UIDesignerBundle.message("error.class.does.not.exist", classToBind), HighlightDisplayLevel.ERROR, fixes); rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, errorInfo); } else { rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, null); } } else { rootContainer.putClientProperty(CLIENT_PROP_CLASS_TO_BIND_ERROR, null); psiClass = null; } // 2. Validate bindings to fields // field name -> error message final ArrayList<String> usedBindings = new ArrayList<>(); // for performance reasons final Set<IButtonGroup> processedGroups = new HashSet<>(); FormEditingUtil.iterate( rootContainer, new FormEditingUtil.ComponentVisitor<>() { @Override public boolean visit(final IComponent component) { if (progress != null && progress.isCanceled()) return false; // Reset previous error (if any) component.putClientProperty(CLIENT_PROP_BINDING_ERROR, null); final String binding = component.getBinding(); // a. Check that field exists and field is not static if (psiClass != null && binding != null) { if (validateFieldInClass(component, binding, component.getComponentClassName(), psiClass, editor, module)) return true; } // b. Check that binding is unique if (binding != null) { if (usedBindings.contains(binding)) { // TODO[vova] implement component.putClientProperty( CLIENT_PROP_BINDING_ERROR, new ErrorInfo( component, null, UIDesignerBundle.message("error.binding.already.exists", binding), HighlightDisplayLevel.ERROR, QuickFix.EMPTY_ARRAY ) ); return true; } usedBindings.add(binding); } IButtonGroup group = FormEditingUtil.findGroupForComponent(rootContainer, component); if (group != null && !processedGroups.contains(group)) { processedGroups.add(group); if (group.isBound()) { validateFieldInClass(component, group.getName(), ButtonGroup.class.getName(), psiClass, editor, module); } } return true; } } ); if (progress != null) progress.checkCanceled(); // Check that there are no panels in XY with children FormEditingUtil.iterate( rootContainer, new FormEditingUtil.ComponentVisitor<>() { @Override public boolean visit(final IComponent component) { if (progress != null && progress.isCanceled()) return false; // Clear previous error (if any) component.putClientProperty(CLIENT_PROP_ERROR_ARRAY, null); if (!(component instanceof IContainer container)) { return true; } if (container instanceof IRootContainer rootContainer) { if (rootContainer.getComponentCount() > 1) { // TODO[vova] implement putError(component, new ErrorInfo( component, null, UIDesignerBundle.message("error.multiple.toplevel.components"), HighlightDisplayLevel.ERROR, QuickFix.EMPTY_ARRAY )); } } else if (container.isXY() && container.getComponentCount() > 0) { // TODO[vova] implement putError(component, new ErrorInfo( component, null, UIDesignerBundle.message("error.panel.not.laid.out"), HighlightDisplayLevel.ERROR, QuickFix.EMPTY_ARRAY ) ); } return true; } } ); if (progress != null) progress.checkCanceled(); try { // Run inspections for form elements final PsiFile formPsiFile = PsiManager.getInstance(module.getProject()).findFile(formFile); if (formPsiFile != null && rootContainer instanceof RadRootContainer) { final List<FormInspectionTool> formInspectionTools = new ArrayList<>(); for (FormInspectionTool formInspectionTool : FormInspectionTool.EP_NAME.getExtensionList()) { if (formInspectionTool.isActive(formPsiFile) && !isSuppressed(rootContainer, formInspectionTool, null)) { formInspectionTools.add(formInspectionTool); } } if (!formInspectionTools.isEmpty() && editor != null) { for (FormInspectionTool tool : formInspectionTools) { tool.startCheckForm(rootContainer); } FormEditingUtil.iterate( rootContainer, (FormEditingUtil.ComponentVisitor<RadComponent>)(RadComponent component) -> { if (progress != null && progress.isCanceled()) return false; for (FormInspectionTool tool : formInspectionTools) { if (isSuppressed(rootContainer, tool, component.getId())) continue; ErrorInfo[] errorInfos = tool.checkComponent(editor, component); if (errorInfos != null) { ArrayList<ErrorInfo> errorList = getErrorInfos(component); if (errorList == null) { errorList = new ArrayList<>(); component.putClientProperty(CLIENT_PROP_ERROR_ARRAY, errorList); } Collections.addAll(errorList, errorInfos); } } return true; } ); for (FormInspectionTool tool : formInspectionTools) { tool.doneCheckForm(rootContainer); } } } } catch (ProcessCanceledException e) { throw e; } catch (Exception e) { LOG.error(e); } }