package com.intellij.flex.uiDesigner.libraries; import com.intellij.flex.uiDesigner.AssetCounter; import com.intellij.flex.uiDesigner.ProblemsHolder; import com.intellij.flex.uiDesigner.css.CssWriter; import com.intellij.flex.uiDesigner.io.ByteArrayOutputStreamEx; import com.intellij.flex.uiDesigner.io.PrimitiveAmfOutputStream; import com.intellij.flex.uiDesigner.io.StringRegistry.StringWriter; import com.intellij.javascript.flex.css.FlexStyleIndex; import com.intellij.javascript.flex.css.FlexStyleIndexInfo; import com.intellij.openapi.module.Module; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.indexing.FileBasedIndex; import gnu.trove.THashSet; import java.util.ArrayList; import java.util.List; import java.util.Set; class LibraryStyleInfoCollector { private final AssetCounter assetCounter; private final Module module; private final PrimitiveAmfOutputStream bytes = new PrimitiveAmfOutputStream(new ByteArrayOutputStreamEx(128)); private final ProblemsHolder problemsHolder; private final StringWriter stringWriter; public LibraryStyleInfoCollector(AssetCounter assetCounter, ProblemsHolder problemsHolder, Module module, StringWriter stringWriter) { this.assetCounter = assetCounter; this.module = module; this.problemsHolder = problemsHolder; this.stringWriter = stringWriter; } private byte[] collectInherited(final VirtualFile jarFile) { bytes.allocateShort(); final VirtualFile libraryFile = Library.getSwfFile(jarFile); final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance(); final GlobalSearchScope searchScope = GlobalSearchScope.fileScope(module.getProject(), libraryFile); final List<String> dataKeys = new ArrayList<>(32); fileBasedIndex.processAllKeys(FlexStyleIndex.INDEX_ID, dataKey -> { dataKeys.add(dataKey); return true; }, module.getProject()); final THashSet<String> uniqueGuard = new THashSet<>(); final FileBasedIndex.ValueProcessor<Set<FlexStyleIndexInfo>> processor = (file, value) -> { final FlexStyleIndexInfo firstInfo = value.iterator().next(); if (firstInfo.getInherit().charAt(0) == 'y' && uniqueGuard.add(firstInfo.getAttributeName())) { bytes.writeUInt29(stringWriter.getReference(firstInfo.getAttributeName()) - 1); } // If the property is defined in the library - we it consider that unique for all library - we make an assumption that // may not be in a class stylePName be inherited, and another class of the same library not inherited return false; }; for (String dataKey : dataKeys) { fileBasedIndex.processValues(FlexStyleIndex.INDEX_ID, dataKey, libraryFile, processor, searchScope); } if (uniqueGuard.isEmpty()) { return null; } else { bytes.putShort(uniqueGuard.size(), 0); return bytes.getByteArrayOut().toByteArray(); } } public void process(Library library, boolean isNew) { if (!isNew) { assetCounter.append(library.assetCounter); return; } try { library.inheritingStyles = collectInherited(library.getFile()); } finally { bytes.reset(); } VirtualFile defaultsCssVirtualFile = library.getDefaultsCssFile(); if (defaultsCssVirtualFile != null) { AssetCounter libAssetCounter = new AssetCounter(); byte[] data = new CssWriter(stringWriter, problemsHolder, libAssetCounter).write(defaultsCssVirtualFile, module); if (data != null) { library.defaultsStyle = data; library.assetCounter = libAssetCounter; assetCounter.append(libAssetCounter); } } } }