PageRenderTime 49ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/netbeans-7.3/cnd.discovery/src/org/netbeans/modules/cnd/discovery/wizard/support/impl/DiscoveryProjectGeneratorImpl.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 1069 lines | 958 code | 34 blank | 77 comment | 329 complexity | 12a0ca89734e848b7ef5be93d7924ec1 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans.modules.cnd.discovery.wizard.support.impl;
  45. import java.io.IOException;
  46. import java.util.ArrayList;
  47. import java.util.Arrays;
  48. import java.util.Collections;
  49. import java.util.HashMap;
  50. import java.util.HashSet;
  51. import java.util.Iterator;
  52. import java.util.LinkedHashSet;
  53. import java.util.List;
  54. import java.util.Map;
  55. import java.util.Set;
  56. import java.util.TreeMap;
  57. import org.netbeans.api.project.Project;
  58. import org.netbeans.modules.cnd.discovery.api.ItemProperties;
  59. import org.netbeans.modules.cnd.discovery.api.ItemProperties.LanguageKind;
  60. import org.netbeans.modules.cnd.discovery.buildsupport.CompileSupport;
  61. import org.netbeans.modules.cnd.discovery.projectimport.ImportProject;
  62. import org.netbeans.modules.cnd.discovery.wizard.api.ConsolidationStrategy;
  63. import org.netbeans.modules.cnd.discovery.wizard.api.DiscoveryDescriptor;
  64. import org.netbeans.modules.cnd.discovery.wizard.api.FileConfiguration;
  65. import org.netbeans.modules.cnd.discovery.wizard.api.ProjectConfiguration;
  66. import org.netbeans.modules.cnd.discovery.wizard.api.support.ProjectBridge;
  67. import org.netbeans.modules.cnd.discovery.wizard.checkedtree.AbstractRoot;
  68. import org.netbeans.modules.cnd.discovery.wizard.checkedtree.UnusedFactory;
  69. import org.netbeans.modules.cnd.makeproject.api.configurations.CCCCompilerConfiguration;
  70. import org.netbeans.modules.cnd.makeproject.api.configurations.CCCompilerConfiguration;
  71. import org.netbeans.modules.cnd.makeproject.api.configurations.CCompilerConfiguration;
  72. import org.netbeans.modules.cnd.makeproject.api.configurations.ConfigurationDescriptorProvider;
  73. import org.netbeans.modules.cnd.makeproject.api.configurations.Folder;
  74. import org.netbeans.modules.cnd.makeproject.api.configurations.Item;
  75. import org.netbeans.modules.cnd.makeproject.api.configurations.MakeConfiguration;
  76. import org.netbeans.modules.cnd.makeproject.api.configurations.MakeConfigurationDescriptor;
  77. import org.netbeans.modules.cnd.utils.CndPathUtilitities;
  78. import org.netbeans.modules.cnd.utils.MIMENames;
  79. import org.openide.filesystems.FileObject;
  80. import org.openide.util.Utilities;
  81. /**
  82. *
  83. * @author Alexander Simon
  84. */
  85. public class DiscoveryProjectGeneratorImpl {
  86. private static boolean DEBUG = Boolean.getBoolean("cnd.discovery.trace.project_update"); // NOI18N
  87. private static boolean TRUNCATE_BEGINNING_PATH = true;
  88. /**
  89. * Old IDE behavior is random user include paths after consolidation.
  90. * Since 7.3 consolidation preserve paths order.
  91. * It can enlarge project's metadata. To forbid preserving use flag:
  92. * <pre>
  93. * -J-Dcnd.discovery.can_violate_paths_order=true
  94. * </pre>
  95. */
  96. private static boolean VIOLATE_PATHS_ORDER = Boolean.getBoolean("cnd.discovery.can_violate_paths_order"); // NOI18N
  97. private ProjectBridge projectBridge;
  98. private DiscoveryDescriptor wizard;
  99. private String baseFolder;
  100. private String level;
  101. /** Creates a new instance of PrjectGenerator */
  102. public DiscoveryProjectGeneratorImpl(DiscoveryDescriptor wizard) throws IOException {
  103. this.wizard = wizard;
  104. baseFolder = wizard.getRootFolder();
  105. Project project = wizard.getProject();
  106. if (project != null) {
  107. projectBridge = new ProjectBridge(project);
  108. } else {
  109. projectBridge = new ProjectBridge(baseFolder);
  110. }
  111. }
  112. private void storeCompileLines(List<ProjectConfiguration> projectConfigurations) {
  113. Project project = wizard.getProject();
  114. if (project != null) {
  115. ConfigurationDescriptorProvider pdp = project.getLookup().lookup(ConfigurationDescriptorProvider.class);
  116. if (pdp != null) {
  117. MakeConfigurationDescriptor makeConfigurationDescriptor = pdp.getConfigurationDescriptor();
  118. if (makeConfigurationDescriptor != null) {
  119. MakeConfiguration activeConfiguration = makeConfigurationDescriptor.getActiveConfiguration();
  120. if (activeConfiguration != null) {
  121. List<FileConfiguration> confs = new ArrayList<FileConfiguration>();
  122. for (ProjectConfiguration config: projectConfigurations){
  123. confs.addAll(config.getFiles());
  124. }
  125. final Iterator<FileConfiguration> iterator = confs.iterator();
  126. CompileSupport support = new CompileSupport();
  127. Iterator<String> it = new Iterator<String>() {
  128. @Override
  129. public boolean hasNext() {
  130. return iterator.hasNext();
  131. }
  132. @Override
  133. public String next() {
  134. FileConfiguration next = iterator.next();
  135. if (next.getCompileLine() != null) {
  136. return next.getFilePath()+"="+next.getCompilePath()+"#"+next.getCompileLine(); // NOI18N
  137. }
  138. return ""; // NOI18N
  139. }
  140. @Override
  141. public void remove() {
  142. throw new UnsupportedOperationException();
  143. }
  144. };
  145. support.putOptions(activeConfiguration, it);
  146. }
  147. }
  148. }
  149. }
  150. }
  151. public void process(){
  152. List<ProjectConfiguration> projectConfigurations = wizard.getConfigurations();
  153. Folder sourceRoot = projectBridge.getRoot();
  154. createFolderStructure(projectConfigurations, sourceRoot);
  155. level = wizard.getLevel();
  156. Set<Item> used = new HashSet<Item>();
  157. for (ProjectConfiguration config: projectConfigurations){
  158. setupCompilerConfiguration(config);
  159. addConfiguration(sourceRoot, config, used);
  160. }
  161. // add other files
  162. addAdditional(sourceRoot, baseFolder, used);
  163. if (TRUNCATE_BEGINNING_PATH) {
  164. packRoot(sourceRoot);
  165. }
  166. if (ConsolidationStrategy.FILE_LEVEL.equals(level)) {// NOI18N
  167. // move common file configuration to parent
  168. upConfiguration(sourceRoot, ItemProperties.LanguageKind.CPP);
  169. upConfiguration(sourceRoot, ItemProperties.LanguageKind.C);
  170. downConfiguration(sourceRoot, ItemProperties.LanguageKind.CPP);
  171. downConfiguration(sourceRoot, ItemProperties.LanguageKind.C);
  172. }
  173. projectBridge.printStaticstic(sourceRoot, ImportProject.logger);
  174. storeCompileLines(projectConfigurations);
  175. projectBridge.save();
  176. projectBridge.dispose();
  177. }
  178. private void packRoot(Folder root) {
  179. for(Object item : root.getElements()) {
  180. if (!(item instanceof Folder)) {
  181. return;
  182. }
  183. }
  184. Map<Folder,Folder> res = new HashMap<Folder,Folder>();
  185. for(Folder folder : root.getFolders()) {
  186. if (folder.getKind() == Folder.Kind.IMPORTANT_FILES_FOLDER) {
  187. res.put(folder,folder);
  188. } else if (folder.isDiskFolder()) {
  189. // do not change disk folder.
  190. res.put(folder,folder);
  191. } else {
  192. Folder packFolder = packFolder(folder);
  193. res.put(folder,packFolder);
  194. }
  195. }
  196. boolean isFullNames = false;
  197. for(int i = 0; i < 3; i++) {
  198. isFullNames = false;
  199. Map<String, List<Map.Entry<Folder,Folder>>> names = new HashMap<String, List<Map.Entry<Folder,Folder>>>();
  200. for(Map.Entry<Folder,Folder> entry : res.entrySet()) {
  201. String folderName = entry.getValue().getName();
  202. List<Map.Entry<Folder,Folder>> list = names.get(folderName);
  203. if (list == null) {
  204. list = new ArrayList<Map.Entry<Folder,Folder>>();
  205. names.put(folderName, list);
  206. }
  207. list.add(entry);
  208. if (list.size() > 1) {
  209. isFullNames = true;
  210. }
  211. }
  212. if (!isFullNames) {
  213. break;
  214. }
  215. for (Map.Entry<String, List<Map.Entry<Folder,Folder>>> entry : names.entrySet()) {
  216. if (entry.getValue().size() > 1) {
  217. for(Map.Entry<Folder,Folder> e : entry.getValue()) {
  218. Folder beg = e.getKey();
  219. Folder end = e.getValue();
  220. Folder up = end.getParent();
  221. if (up != null && up != beg) {
  222. res.put(beg, up);
  223. } else {
  224. // cannot resolve name conflict
  225. return;
  226. }
  227. }
  228. }
  229. }
  230. }
  231. if (isFullNames) {
  232. // cannot resolve name conflict
  233. return;
  234. }
  235. List<Object> elements = root.getElements();
  236. if (res.size() == elements.size()) {
  237. boolean equals = true;
  238. for(Map.Entry<Folder,Folder> entry : res.entrySet()) {
  239. if (elements.indexOf(entry.getValue()) < 0) {
  240. equals = false;
  241. }
  242. }
  243. if (equals) {
  244. for(Map.Entry<Folder,Folder> entry : res.entrySet()) {
  245. if (entry.getKey().getKind() == Folder.Kind.IMPORTANT_FILES_FOLDER) {
  246. continue;
  247. } else if (entry.getValue().isDiskFolder()) {
  248. continue;
  249. } else {
  250. if (entry.getValue().getRoot() == null) {
  251. FileObject folderFile = getFolderFile(entry.getValue());
  252. if (folderFile != null) {
  253. entry.getValue().setRoot(projectBridge.getRelativepath(folderFile.getPath()));
  254. }
  255. }
  256. }
  257. }
  258. return;
  259. }
  260. }
  261. root.reset();
  262. for(Map.Entry<Folder,Folder> entry : res.entrySet()) {
  263. if (entry.getKey().getKind() == Folder.Kind.IMPORTANT_FILES_FOLDER) {
  264. root.addFolder(entry.getValue(), true);
  265. continue;
  266. } else if (entry.getValue().isDiskFolder()) {
  267. root.addFolder(entry.getValue(), true);
  268. } else {
  269. if (entry.getValue().getRoot() == null) {
  270. FileObject folderFile = getFolderFile(entry.getValue());
  271. if (folderFile != null) {
  272. entry.getValue().setRoot(projectBridge.getRelativepath(folderFile.getPath()));
  273. }
  274. }
  275. root.addFolder(entry.getValue(), true);
  276. }
  277. }
  278. }
  279. private FileObject getFolderFile(Folder folder) {
  280. for(Item item : folder.getItemsAsArray()) {
  281. FileObject fo = item.getFileObject();
  282. if (fo != null) {
  283. FileObject parent = fo.getParent();
  284. if (parent != null) {
  285. return parent;
  286. }
  287. }
  288. }
  289. for(Folder f : folder.getFolders()) {
  290. FileObject folderObject = getFolderFile(f);
  291. if (folderObject != null) {
  292. FileObject parent = folderObject.getParent();
  293. if (parent != null) {
  294. return parent;
  295. }
  296. }
  297. }
  298. return null;
  299. }
  300. private Folder packFolder(Folder folder) {
  301. while(true) {
  302. if (folder.getElements().size() > 1) {
  303. return folder;
  304. }
  305. List<Folder> folders = folder.getFolders();
  306. if (folders.isEmpty()) {
  307. return folder;
  308. }
  309. folder = folders.get(0);
  310. }
  311. }
  312. private void downConfiguration(Folder folder, ItemProperties.LanguageKind lang) {
  313. CCCCompilerConfiguration cccc = projectBridge.getFolderConfiguration(lang, folder);
  314. if (cccc != null) {
  315. List<String> commonFoldersIncludes = cccc.getIncludeDirectories().getValue();
  316. List<String> commonFoldersMacros = cccc.getPreprocessorConfiguration().getValue();
  317. List<String> commonFoldersUndefs = cccc.getUndefinedPreprocessorConfiguration().getValue();
  318. projectBridge.setupProject(commonFoldersIncludes, commonFoldersMacros, commonFoldersUndefs, lang);
  319. projectBridge.setupFolder(Collections.<String>emptyList(), true,
  320. Collections.<String>emptyList(), true,
  321. Collections.<String>emptyList(), true, lang, folder);
  322. downConfiguration(folder, lang, commonFoldersIncludes, commonFoldersMacros, commonFoldersUndefs);
  323. }
  324. }
  325. private void downConfiguration(Folder folder, ItemProperties.LanguageKind lang, List<String> commonFoldersIncludes, List<String> commonFoldersMacros, List<String> commonFoldersUndefs) {
  326. for(Folder subFolder : folder.getFoldersAsArray()){
  327. CCCCompilerConfiguration cccc = projectBridge.getFolderConfiguration(lang, subFolder);
  328. if (cccc == null) {
  329. continue;
  330. }
  331. List<String> aCommonFoldersIncludes = new ArrayList<String>(commonFoldersIncludes);
  332. List<String> aCommonFoldersMacros = new ArrayList<String>(commonFoldersMacros);
  333. List<String> aCommonFoldersUndefs = new ArrayList<String>(commonFoldersUndefs);
  334. List<String> foldersIncludes = new ArrayList<String>();
  335. List<String> foldersMacros = new ArrayList<String>();
  336. List<String> foldersUndefs = new ArrayList<String>();
  337. for(String s : cccc.getIncludeDirectories().getValue()){
  338. if (!aCommonFoldersIncludes.contains(s)) {
  339. foldersIncludes.add(s);
  340. aCommonFoldersIncludes.add(s);
  341. }
  342. }
  343. for(String s : cccc.getPreprocessorConfiguration().getValue()){
  344. if (!aCommonFoldersMacros.contains(s)) {
  345. foldersMacros.add(s);
  346. aCommonFoldersMacros.add(s);
  347. }
  348. }
  349. for(String s : cccc.getUndefinedPreprocessorConfiguration().getValue()){
  350. if (!aCommonFoldersUndefs.contains(s)) {
  351. foldersUndefs.add(s);
  352. aCommonFoldersUndefs.add(s);
  353. }
  354. }
  355. projectBridge.setupFolder(foldersIncludes, true, foldersMacros, true, foldersUndefs, true, lang, subFolder);
  356. downConfiguration(subFolder, lang, aCommonFoldersIncludes, aCommonFoldersMacros, aCommonFoldersUndefs);
  357. }
  358. }
  359. private Folder getOrCreateFolder(Folder folder, String name, AbstractRoot used) {
  360. Folder added = null;
  361. Folder[] folders = folder.getFoldersAsArray();
  362. for (int i = 0; i < folders.length; i++) {
  363. String root = folders[i].getAbsolutePath();
  364. String orphan = used.getFolder();
  365. if (root != null && orphan != null && orphan.startsWith(root)) {
  366. String[] splitRoot = root.split("\\/"); // NOI18N
  367. String[] splitOrphan = orphan.split("\\/"); // NOI18N
  368. int lastEquals = -1;
  369. for(int j = 0; j < splitRoot.length && j < splitOrphan.length; j++) {
  370. if (splitRoot[j].equals(splitOrphan[j])) {
  371. lastEquals = j;
  372. } else {
  373. break;
  374. }
  375. }
  376. if (lastEquals == splitRoot.length - 1) {
  377. // ophan is subfolder of root
  378. added = folders[i];
  379. for(int j = lastEquals + 1; j < splitOrphan.length; j++) {
  380. Folder found = null;
  381. for(Folder current : added.getFoldersAsArray()) {
  382. if (current.getName().equals(splitOrphan[j])) {
  383. found = current;
  384. break;
  385. }
  386. }
  387. if (found == null) {
  388. found = projectBridge.createFolder(added, splitOrphan[j]);
  389. added.addFolder(found, true);
  390. }
  391. added = found;
  392. }
  393. break;
  394. }
  395. }
  396. if (name != null && name.equals(folders[i].getName())) {
  397. added = folders[i];
  398. break;
  399. }
  400. }
  401. if (added == null) {
  402. added = projectBridge.createFolder(folder, name);
  403. //if (!folder.isDiskFolder()) {
  404. // String additionalPath = used.getFolder();
  405. // added.setRoot(CndPathUtilitities.toRelativePath(folder.getConfigurationDescriptor().getBaseDir(), additionalPath));
  406. // projectBridge.addSourceRoot(additionalPath);
  407. //}
  408. folder.addFolder(added, true);
  409. } else {
  410. if (added.isDiskFolder()) {
  411. String additionalPath = used.getFolder();
  412. String folderPath = CndPathUtilitities.toAbsolutePath(folder.getConfigurationDescriptor().getBaseDirFileObject(), added.getRootPath());
  413. Folder logicalCandidate = null;
  414. if (!additionalPath.equals(folderPath)) {
  415. for (Folder candidate : folder.getFolders()) {
  416. if (candidate.isDiskFolder()) {
  417. folderPath = CndPathUtilitities.toAbsolutePath(folder.getConfigurationDescriptor().getBaseDirFileObject(), candidate.getRootPath());
  418. if (additionalPath.equals(folderPath)) {
  419. added = candidate;
  420. break;
  421. }
  422. } else if (logicalCandidate == null && candidate.getName().equals(name)) {
  423. logicalCandidate = candidate;
  424. }
  425. }
  426. }
  427. if (!additionalPath.equals(folderPath)) {
  428. if (logicalCandidate == null) {
  429. added = projectBridge.createFolder(folder, name);
  430. //added.setRoot(CndPathUtilitities.toRelativePath(folder.getConfigurationDescriptor().getBaseDir(), additionalPath));
  431. //projectBridge.addSourceRoot(additionalPath);
  432. folder.addFolder(added, true);
  433. } else {
  434. added = logicalCandidate;
  435. }
  436. }
  437. }
  438. }
  439. return added;
  440. }
  441. private boolean upConfiguration(Folder folder, ItemProperties.LanguageKind lang) {
  442. Set<String> commonFoldersIncludes = new LinkedHashSet<String>();
  443. MacroMap commonFolderMacroMap = new MacroMap();
  444. Set<String> commonFoldersUndefs = new HashSet<String>();
  445. boolean haveSubFolders = false;
  446. for (Folder subFolder : folder.getFolders()) {
  447. if (!upConfiguration(subFolder, lang)){
  448. continue;
  449. }
  450. if (!haveSubFolders) {
  451. CCCCompilerConfiguration cccc = projectBridge.getFolderConfiguration(lang, subFolder);
  452. if (cccc != null) {
  453. commonFoldersIncludes.addAll(cccc.getIncludeDirectories().getValue());
  454. commonFolderMacroMap.addAll(cccc.getPreprocessorConfiguration().getValue());
  455. commonFoldersUndefs.addAll(cccc.getUndefinedPreprocessorConfiguration().getValue());
  456. haveSubFolders = true;
  457. }
  458. } else {
  459. if (commonFoldersIncludes.size() > 0) {
  460. CCCCompilerConfiguration cccc = projectBridge.getFolderConfiguration(lang, subFolder);
  461. if (cccc != null) {
  462. if (VIOLATE_PATHS_ORDER) {
  463. commonFoldersIncludes.retainAll(cccc.getIncludeDirectories().getValue());
  464. } else {
  465. List<String> itemPaths = cccc.getIncludeDirectories().getValue();
  466. int min = Math.min(commonFoldersIncludes.size(), itemPaths.size());
  467. Iterator<String> it1 = commonFoldersIncludes.iterator();
  468. Iterator<String> it2 = itemPaths.iterator();
  469. int last = min;
  470. for(int i = 0; i < min; i++) {
  471. String next1 = it1.next();
  472. String next2 = it2.next();
  473. if (!next1.equals(next2)) {
  474. last = i;
  475. break;
  476. }
  477. }
  478. commonFoldersIncludes = new LinkedHashSet<String>();
  479. if (last > 0) {
  480. for(int i = 0; i < last; i++) {
  481. commonFoldersIncludes.add(itemPaths.get(i));
  482. }
  483. }
  484. }
  485. }
  486. }
  487. if (commonFolderMacroMap.size() > 0) {
  488. CCCCompilerConfiguration cccc = projectBridge.getFolderConfiguration(lang, subFolder);
  489. if (cccc != null) {
  490. commonFolderMacroMap.retainAll(cccc.getPreprocessorConfiguration().getValue());
  491. }
  492. }
  493. if (commonFoldersUndefs.size() > 0) {
  494. CCCCompilerConfiguration cccc = projectBridge.getFolderConfiguration(lang, subFolder);
  495. if (cccc != null) {
  496. commonFoldersUndefs.retainAll(cccc.getUndefinedPreprocessorConfiguration().getValue());
  497. }
  498. }
  499. }
  500. }
  501. Set<String> commonFilesIncludes = new LinkedHashSet<String>();
  502. MacroMap commonFilesMacroMap = new MacroMap();
  503. Set<String> commonFilesUndefs = new HashSet<String>();
  504. boolean first = true;
  505. if (haveSubFolders) {
  506. commonFilesIncludes = new LinkedHashSet<String>(commonFoldersIncludes);
  507. commonFilesMacroMap = new MacroMap(commonFolderMacroMap);
  508. commonFilesUndefs = new HashSet<String>(commonFoldersUndefs);
  509. first = false;
  510. }
  511. for (Item item : folder.getItemsAsArray()) {
  512. if (item.isExcluded()){
  513. continue;
  514. }
  515. CCCCompilerConfiguration cccc = projectBridge.getItemConfiguration(item);
  516. if (lang == ItemProperties.LanguageKind.CPP) {
  517. if (!(cccc instanceof CCCompilerConfiguration)) {
  518. continue;
  519. }
  520. } else if (lang == ItemProperties.LanguageKind.C) {
  521. if (!(cccc instanceof CCompilerConfiguration)) {
  522. continue;
  523. }
  524. } else {
  525. continue;
  526. }
  527. if (first) {
  528. commonFilesIncludes.addAll(cccc.getIncludeDirectories().getValue());
  529. commonFilesMacroMap.addAll(cccc.getPreprocessorConfiguration().getValue());
  530. commonFilesUndefs.addAll(cccc.getUndefinedPreprocessorConfiguration().getValue());
  531. first = false;
  532. } else {
  533. if (commonFilesIncludes.size() > 0) {
  534. if (VIOLATE_PATHS_ORDER) {
  535. commonFilesIncludes.retainAll(cccc.getIncludeDirectories().getValue());
  536. } else {
  537. List<String> itemPaths = cccc.getIncludeDirectories().getValue();
  538. int min = Math.min(commonFilesIncludes.size(), itemPaths.size());
  539. Iterator<String> it1 = commonFilesIncludes.iterator();
  540. Iterator<String> it2 = itemPaths.iterator();
  541. int last = min;
  542. for(int i = 0; i < min; i++) {
  543. String next1 = it1.next();
  544. String next2 = it2.next();
  545. if (!next1.equals(next2)) {
  546. last = i;
  547. break;
  548. }
  549. }
  550. commonFilesIncludes = new LinkedHashSet<String>();
  551. if (last > 0) {
  552. for(int i = 0; i < last; i++) {
  553. commonFilesIncludes.add(itemPaths.get(i));
  554. }
  555. }
  556. }
  557. }
  558. if (commonFilesMacroMap.size() > 0) {
  559. commonFilesMacroMap.retainAll(cccc.getPreprocessorConfiguration().getValue());
  560. }
  561. if (commonFilesUndefs.size() > 0) {
  562. commonFilesUndefs.retainAll(cccc.getUndefinedPreprocessorConfiguration().getValue());
  563. }
  564. }
  565. }
  566. if (commonFilesIncludes.size() > 0 || commonFilesMacroMap.size() > 0 || commonFilesUndefs.size() > 0) {
  567. for (Item item : folder.getItemsAsArray()) {
  568. CCCCompilerConfiguration cccc = projectBridge.getItemConfiguration(item);
  569. if (lang == ItemProperties.LanguageKind.CPP) {
  570. if (!(cccc instanceof CCCompilerConfiguration)) {
  571. continue;
  572. }
  573. } else if (lang == ItemProperties.LanguageKind.C) {
  574. if (!(cccc instanceof CCompilerConfiguration)) {
  575. continue;
  576. }
  577. } else {
  578. continue;
  579. }
  580. if (commonFilesIncludes.size() > 0) {
  581. List<String> list = new ArrayList<String>(cccc.getIncludeDirectories().getValue());
  582. list.removeAll(commonFilesIncludes);
  583. cccc.getIncludeDirectories().setValue(list);
  584. }
  585. if (commonFilesMacroMap.size() > 0) {
  586. List<String> list = new ArrayList<String>(cccc.getPreprocessorConfiguration().getValue());
  587. list = commonFilesMacroMap.removeCommon(list);
  588. cccc.getPreprocessorConfiguration().setValue(list);
  589. }
  590. if (commonFilesUndefs.size() > 0) {
  591. List<String> list = new ArrayList<String>(cccc.getUndefinedPreprocessorConfiguration().getValue());
  592. list.removeAll(commonFilesUndefs);
  593. cccc.getUndefinedPreprocessorConfiguration().setValue(list);
  594. }
  595. }
  596. }
  597. CCCCompilerConfiguration cccc = projectBridge.getFolderConfiguration(lang, folder);
  598. if (cccc != null) {
  599. if (commonFilesIncludes.size() > 0) {
  600. cccc.getIncludeDirectories().setValue(new ArrayList<String>(commonFilesIncludes));
  601. }
  602. if (commonFilesMacroMap.size() > 0) {
  603. cccc.getPreprocessorConfiguration().setValue(commonFilesMacroMap.convertToList());
  604. }
  605. if (commonFilesUndefs.size() > 0) {
  606. cccc.getUndefinedPreprocessorConfiguration().setValue(new ArrayList<String>(commonFilesUndefs));
  607. }
  608. }
  609. return !first;
  610. }
  611. public Set<Project> makeProject(){
  612. if (projectBridge.isValid() && wizard.getConfigurations() != null && wizard.getConfigurations().size() > 0) {
  613. projectBridge.startModifications();
  614. process();
  615. return projectBridge.getResult();
  616. }
  617. return Collections.<Project>emptySet();
  618. }
  619. private Set<String> getSourceFolders(){
  620. Set<String> used = new HashSet<String>();
  621. List<ProjectConfiguration> projectConfigurations = wizard.getConfigurations();
  622. for (ProjectConfiguration conf : projectConfigurations) {
  623. for (FileConfiguration file : conf.getFiles()){
  624. String path = file.getFilePath();
  625. if (Utilities.isWindows()) {
  626. path = path.replace('\\', '/');
  627. }
  628. int i = path.lastIndexOf('/');
  629. if (i > 0) {
  630. path = path.substring(0,i+1);
  631. }
  632. used.add(path);
  633. }
  634. }
  635. used.addAll(compureRoots(used));
  636. return used;
  637. }
  638. private Set<String> compureRoots(Set<String> roots) {
  639. Set<String> res = new HashSet<String>();
  640. ArrayList<String> root = null;
  641. for(String s : roots) {
  642. if (root == null) {
  643. root = new ArrayList<String>();
  644. root.addAll(Arrays.asList(s.split("/"))); // NOI18N
  645. continue;
  646. }
  647. int i = 0;
  648. for(String segment : s.split("/")) { // NOI18N
  649. if (i < root.size()) {
  650. if (!segment.equals(root.get(i))) {
  651. while(root.size() > i) {
  652. root.remove(root.size()-1);
  653. }
  654. }
  655. } else {
  656. break;
  657. }
  658. i++;
  659. }
  660. }
  661. if (root != null && root.size() > 1) {
  662. StringBuilder buf = new StringBuilder();
  663. for(String s : root) {
  664. buf.append(s);
  665. buf.append('/');
  666. }
  667. res.add(buf.toString());
  668. }
  669. return res;
  670. }
  671. private void addAdditional(Folder folder, String base, Set<Item> usedItems){
  672. Set<String> folders = getSourceFolders();
  673. Set<String> used = new HashSet<String>();
  674. Set<String> needAdd = new HashSet<String>();
  675. Set<String> needCheck = new HashSet<String>();
  676. List<String> list = wizard.getIncludedFiles();
  677. Map<String,Folder> preffered = projectBridge.prefferedFolders();
  678. for (String name : list){
  679. used.add(name);
  680. String path = projectBridge.getRelativepath(name);
  681. Item item = projectBridge.getProjectItem(path);
  682. if (item == null){
  683. path = name;
  684. if (Utilities.isWindows()) {
  685. path = path.replace('\\', '/');
  686. }
  687. boolean isNeedAdd = false;
  688. if (path.startsWith(base)){
  689. isNeedAdd = true;
  690. } else {
  691. for(String dir : folders){
  692. if (path.startsWith(dir)){
  693. isNeedAdd = true;
  694. break;
  695. }
  696. }
  697. }
  698. if (isNeedAdd){
  699. int i = path.lastIndexOf('/');
  700. if (i >= 0){
  701. String folderPath = path.substring(0,i);
  702. Folder prefferedFolder = preffered.get(folderPath);
  703. if (prefferedFolder != null) {
  704. item = projectBridge.createItem(name);
  705. item = prefferedFolder.addItem(item);
  706. ProjectBridge.setHeaderTool(item);
  707. if(!MIMENames.isCppOrCOrFortran(item.getMIMEType())){
  708. needCheck.add(path);
  709. } else {
  710. if (DEBUG) {System.err.println("Source is header:"+item.getAbsPath());} // NOI18N
  711. }
  712. ProjectBridge.excludeItemFromOtherConfigurations(item);
  713. isNeedAdd = false;
  714. }
  715. }
  716. }
  717. if (isNeedAdd){
  718. needCheck.add(path);
  719. needAdd.add(name);
  720. }
  721. } else {
  722. if (!usedItems.contains(item)) {
  723. if (true || !ConfigurationDescriptorProvider.VCS_WRITE) {
  724. ProjectBridge.setExclude(item,false);
  725. }
  726. ProjectBridge.setHeaderTool(item);
  727. } else {
  728. if(!MIMENames.isCppOrCOrFortran(item.getMIMEType())){
  729. needCheck.add(path);
  730. }
  731. }
  732. }
  733. }
  734. if (needAdd.size()>0) {
  735. AbstractRoot additional = UnusedFactory.createRoot(needAdd, projectBridge.getBaseFolderFileSystem());
  736. if (additional.getName().isEmpty()) {
  737. for(AbstractRoot aRoot : additional.getChildren()) {
  738. addAdditionalPreferedFolder(folder, aRoot);
  739. }
  740. } else {
  741. addAdditionalPreferedFolder(folder, additional);
  742. }
  743. }
  744. // remove unused
  745. List<ProjectConfiguration> projectConfigurations = wizard.getConfigurations();
  746. for (ProjectConfiguration conf : projectConfigurations) {
  747. for (FileConfiguration file : conf.getFiles()){
  748. used.add(file.getFilePath());
  749. }
  750. }
  751. Set<String> relatives = new HashSet<String>();
  752. for (String name : used){
  753. relatives.add(projectBridge.getRelativepath(name));
  754. }
  755. TreeMap<String,Item> sorted = new TreeMap<String,Item>();
  756. for (Item item : projectBridge.getAllSources()){
  757. if (!usedItems.contains(item)) {
  758. sorted.put(item.getPath(),item);
  759. }
  760. }
  761. for (Map.Entry<String,Item> entry : sorted.entrySet()){
  762. String path = entry.getKey();
  763. Item item = entry.getValue();
  764. String canonicalPath = item.getNormalizedPath();
  765. if (!(relatives.contains(path) || used.contains(path) ||
  766. relatives.contains(canonicalPath) || used.contains(canonicalPath))) {
  767. // remove item;
  768. if (DEBUG) {System.out.println("Exclude Item "+path);} // NOI18N
  769. ProjectBridge.setExclude(item,true);
  770. }
  771. }
  772. if (needCheck.size()>0) {
  773. projectBridge.checkForNewExtensions(needCheck);
  774. }
  775. }
  776. private void addAdditionalPreferedFolder(Folder folder, AbstractRoot additional){
  777. Folder rootCandidate = null;
  778. String root = additional.getFolder();
  779. if (Utilities.isWindows()) {
  780. root = root.replace('\\', '/');
  781. }
  782. int i = root.lastIndexOf('/');
  783. if (i > 0) {
  784. Map<String, Folder> prefferedFolders = projectBridge.prefferedFolders();
  785. root = root.substring(0,i);
  786. rootCandidate = prefferedFolders.get(root);
  787. }
  788. if (rootCandidate == null) {
  789. rootCandidate = folder;
  790. }
  791. addAdditionalFolder(rootCandidate, additional);
  792. }
  793. private void addAdditionalFolder(Folder folder, AbstractRoot used){
  794. String name = used.getName();
  795. Folder added = getOrCreateFolder(folder, name, used);
  796. if (added == null) {
  797. added = projectBridge.createFolder(folder, name);
  798. folder.addFolder(added, true);
  799. }
  800. for(AbstractRoot sub : used.getChildren()){
  801. addAdditionalFolder(added, sub);
  802. }
  803. List<String> files = used.getFiles();
  804. if (files != null) {
  805. for(String file : files){
  806. String path = projectBridge.getRelativepath(file);
  807. Item item = projectBridge.getProjectItem(path);
  808. if (item!=null) {
  809. if (item.getFolder() != added){
  810. Object old = projectBridge.getAuxObject(item);
  811. item.getFolder().removeItem(item);
  812. item = added.addItem(item);
  813. if (old != null) {
  814. projectBridge.setAuxObject(item, old);
  815. }
  816. }
  817. if (true || !ConfigurationDescriptorProvider.VCS_WRITE) {
  818. ProjectBridge.setExclude(item,false);
  819. }
  820. ProjectBridge.setHeaderTool(item);
  821. } else {
  822. item = projectBridge.createItem(file);
  823. item = added.addItem(item);
  824. if (true || !ConfigurationDescriptorProvider.VCS_WRITE) {
  825. ProjectBridge.setExclude(item,false);
  826. }
  827. ProjectBridge.setHeaderTool(item);
  828. ProjectBridge.excludeItemFromOtherConfigurations(item);
  829. }
  830. }
  831. }
  832. }
  833. private void setupCompilerConfiguration(ProjectConfiguration config){
  834. if (ConsolidationStrategy.PROJECT_LEVEL.equals(level)){ // NOI18N
  835. Set<String> set = new HashSet<String>();
  836. Map<String,String> macros = new HashMap<String,String>();
  837. Set<String> undefs = new HashSet<String>();
  838. for(FileConfiguration file : config.getFiles()){
  839. reConsolidatePaths(set, file);
  840. macros.putAll(file.getUserMacros());
  841. undefs.addAll(file.getUndefinedMacros());
  842. }
  843. projectBridge.setupProject(new ArrayList<String>(set), buildMacrosString(macros), new ArrayList<String>(undefs), config.getLanguageKind());
  844. } else {
  845. // cleanup project configuration
  846. projectBridge.setupProject(Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList(), config.getLanguageKind());
  847. }
  848. }
  849. private List<String> buildMacrosString(final Map<String, String> map) {
  850. List<String> vector = new ArrayList<String>();
  851. for(Map.Entry<String,String> entry : map.entrySet()){
  852. if (entry.getValue()!=null) {
  853. vector.add(entry.getKey()+"="+entry.getValue()); // NOI18N
  854. } else {
  855. vector.add(entry.getKey());
  856. }
  857. }
  858. return vector;
  859. }
  860. private void setupFile(FileConfiguration config, Item item, ItemProperties.LanguageKind lang) {
  861. ProjectBridge.setSourceTool(item,lang, config.getLanguageStandard(), wizard.isIncrementalMode());
  862. if (ConsolidationStrategy.FILE_LEVEL.equals(level)){ // NOI18N
  863. LinkedHashSet<String> set = new LinkedHashSet<String>();
  864. Map<String,String> macros = new HashMap<String,String>();
  865. reConsolidatePaths(set, config);
  866. macros.putAll(config.getUserMacros());
  867. projectBridge.setupFile(config.getCompilePath(), new ArrayList<String>(set), !config.overrideIncludes(),
  868. buildMacrosString(macros), !config.overrideMacros(),
  869. new ArrayList<String>(config.getUndefinedMacros()), !config.overrideUndefinedMacros(), item);
  870. } else {
  871. // cleanup file configuration
  872. projectBridge.setupFile(config.getCompilePath(), Collections.<String>emptyList(), true,
  873. Collections.<String>emptyList(), true,
  874. Collections.<String>emptyList(), true, item);
  875. }
  876. }
  877. private void reConsolidatePaths(Set<String> set, FileConfiguration file){
  878. projectBridge.convertIncludePaths(set, file.getUserInludePaths(), file.getCompilePath(), file.getFilePath());
  879. }
  880. private void createFolderStructure(List<ProjectConfiguration> projectConfigurations, Folder sourceRoot ){
  881. Map<String,Set<Pair>> configurationStructure = new HashMap<String,Set<Pair>>();
  882. for (ProjectConfiguration config: projectConfigurations){
  883. analyzeConfigurationStructure(config.getFiles(), config.getLanguageKind(), configurationStructure);
  884. }
  885. List<Pair> orphan = detectOrphan(configurationStructure, null);
  886. if (orphan.size() > 0) {
  887. createOrphan(sourceRoot, orphan, null);
  888. }
  889. }
  890. private void addConfiguration(Folder sourceRoot, ProjectConfiguration conf, Set<Item> used){
  891. ItemProperties.LanguageKind lang = conf.getLanguageKind();
  892. Map<String,Set<Pair>> configurationStructure = new HashMap<String,Set<Pair>>();
  893. analyzeConfigurationStructure(conf.getFiles(), lang, configurationStructure);
  894. List<Pair> orphan = detectOrphan(configurationStructure, lang);
  895. if (orphan.size() > 0) {
  896. createOrphan(sourceRoot, orphan, lang);
  897. }
  898. if (ConsolidationStrategy.FOLDER_LEVEL.equals(level)){ // NOI18N
  899. // reconsolidate folders;
  900. Map<Folder,Set<FileConfiguration>> folders = new HashMap<Folder,Set<FileConfiguration>>();
  901. for(Map.Entry<String,Set<Pair>> entry : configurationStructure.entrySet()){
  902. Set<Pair> files = entry.getValue();
  903. for(Pair pair : files){
  904. if (pair.item != null) {
  905. Folder folder = pair.item.getFolder();
  906. Set<FileConfiguration> content = folders.get(folder);
  907. if (content == null){
  908. content = new HashSet<FileConfiguration>();
  909. folders.put(folder,content);
  910. }
  911. content.add(pair.fileConfiguration);
  912. } else {
  913. if (DEBUG) {System.err.println("Cannot find pair by path "+pair.fileConfiguration.getFilePath());} // NOI18N
  914. }
  915. }
  916. }
  917. for(Map.Entry<Folder,Set<FileConfiguration>> entry : folders.entrySet()){
  918. Folder folder = entry.getKey();
  919. Set<FileConfiguration> confs = entry.getValue();
  920. Set<String> inludes = new HashSet<String>();
  921. Map<String,String> macros = new HashMap<String,String>();
  922. Set<String> undefs = new HashSet<String>();
  923. for(FileConfiguration file : confs){
  924. reConsolidatePaths(inludes, file);
  925. macros.putAll(file.getUserMacros());
  926. undefs.addAll(file.getUndefinedMacros());
  927. }
  928. projectBridge.setupFolder(new ArrayList<String>(inludes), false, buildMacrosString(macros), false, new ArrayList<String>(undefs), false, conf.getLanguageKind(), folder);
  929. }
  930. } else {
  931. // cleanup folder configurations
  932. Set<Folder> folders = new HashSet<Folder>();
  933. for(Map.Entry<String,Set<Pair>> entry : configurationStructure.entrySet()){
  934. Set<Pair> files = entry.getValue();
  935. for(Pair pair : files){
  936. if (pair.item != null) {
  937. Folder folder = pair.item.getFolder();
  938. folders.add(folder);
  939. }
  940. }
  941. }
  942. for(Folder folder : folders){
  943. projectBridge.setupFolder(Collections.<String>emptyList(), true, Collections.<String>emptyList(), true, Collections.<String>emptyList(), true, conf.getLanguageKind(), folder);
  944. }
  945. }
  946. for(Set<Pair> set : configurationStructure.values()){
  947. for(Pair pair : set){
  948. if (pair.item != null){
  949. used.add(pair.item);
  950. }
  951. }
  952. }
  953. }
  954. private void createOrphan(Folder sourceRoot, List<Pair> orphan, ItemProperties.LanguageKind lang){
  955. Map<String,Pair> folders = new HashMap<String,Pair>();
  956. for(Pair pair : orphan){
  957. String path = pair.fileConfiguration.getFilePath();
  958. folders.put(path,pair);
  959. }
  960. AbstractRoot additional = UnusedFactory.createRoot(folders.keySet(), projectBridge.getBaseFolderFileSystem());
  961. if (additional.getName().isEmpty()) {
  962. for(AbstractRoot aRoot : additional.getChildren()) {
  963. addFolder(sourceRoot, aRoot, folders, lang);
  964. }
  965. } else {
  966. addFolder(sourceRoot, additional, folders, lang);
  967. }
  968. }
  969. private void addFolder(Folder folder, AbstractRoot additional, Map<String,Pair> folders, ItemProperties.LanguageKind lang){
  970. String name = additional.getName();
  971. Folder added = getOrCreateFolder(folder, name, additional);
  972. for(AbstractRoot sub : additional.getChildren()){
  973. addFolder(added, sub, folders, lang);
  974. }
  975. for(String file : additional.getFiles()){
  976. Pair pair = folders.get(file);
  977. if (pair != null) {
  978. String path = projectBridge.getRelativepath(file);
  979. Item item = projectBridge.getProjectItem(path);
  980. if (item == null){
  981. item = projectBridge.createItem(file);
  982. item = added.addItem(item);
  983. if (item != null) {
  984. ProjectBridge.excludeItemFromOtherConfigurations(item);
  985. }
  986. } else {
  987. if (DEBUG) {System.err.println("Orphan pair found by path "+file);} // NOI18N
  988. }
  989. pair.item = item;
  990. if (lang != null) {
  991. setupFile(pair.fileConfiguration, pair.item, lang);
  992. }
  993. } else {
  994. if (DEBUG) {System.err.println("Cannot find pair by path "+file);} // NOI18N
  995. }
  996. }
  997. }
  998. private List<Pair> detectOrphan(final Map<String, Set<Pair>> configurationStructure, ItemProperties.LanguageKind lang) {
  999. Map<String,Folder> preffered = projectBridge.prefferedFolders();
  1000. List<Pair> orphan = new ArrayList<Pair>();
  1001. for(Map.Entry<String,Set<Pair>> entry : configurationStructure.entrySet()){
  1002. Set<Pair> files = entry.getValue();
  1003. Folder folder = null;
  1004. List<Pair> list = new ArrayList<Pair>();
  1005. for(Pair pair : files){
  1006. Item item = pair.item;
  1007. if (item != null){
  1008. if (folder != null) {
  1009. folder = item.getFolder();
  1010. }
  1011. } else {
  1012. String prefferedFolder = pair.fileConfiguration.getFilePath();
  1013. if (Utilities.isWindows()) {
  1014. prefferedFolder = prefferedFolder.replace('\\', '/'); // NOI18N
  1015. }
  1016. int i = prefferedFolder.lastIndexOf('/'); // NOI18N
  1017. if (i >= 0){
  1018. prefferedFolder = prefferedFolder.substring(0,i);
  1019. folder = preffered.get(prefferedFolder);
  1020. }
  1021. //if (folder == null) {
  1022. list.add(pair);
  1023. //}
  1024. }
  1025. }
  1026. if (folder != null) {
  1027. for(Pair pair : list){
  1028. String relPath = projectBridge.getRelativepath(pair.fileConfiguration.getFilePath());
  1029. Item item = projectBridge.getProjectItem(relPath);
  1030. if (item == null){
  1031. item = projectBridge.createItem(pair.fileConfiguration.getFilePath());
  1032. pair.item = item;
  1033. item = folder.addItem(item);
  1034. if (item != null) {
  1035. Projec