Source Code Cross Referenced for FileImpl.java in  » IDE-Netbeans » cnd » org » netbeans » modules » cnd » modelimpl » csm » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » cnd » org.netbeans.modules.cnd.modelimpl.csm.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.cnd.modelimpl.csm.core;
0043:
0044:        import antlr.Token;
0045:        import antlr.TokenStream;
0046:        import antlr.TokenStreamException;
0047:        import antlr.collections.AST;
0048:        import java.util.concurrent.CopyOnWriteArrayList;
0049:        import java.util.concurrent.locks.ReentrantReadWriteLock;
0050:        import org.netbeans.modules.cnd.api.model.*;
0051:        import org.netbeans.modules.cnd.api.model.util.CsmTracer;
0052:        import org.netbeans.modules.cnd.apt.support.APTHandlersSupport;
0053:        import org.netbeans.modules.cnd.modelimpl.debug.Diagnostic;
0054:        import org.netbeans.modules.cnd.modelimpl.debug.TraceFlags;
0055:        import org.netbeans.modules.cnd.modelimpl.parser.CPPParserEx;
0056:
0057:        import java.io.*;
0058:        import java.lang.ref.Reference;
0059:        import java.lang.ref.SoftReference;
0060:        import java.util.*;
0061:        import java.util.concurrent.locks.ReadWriteLock;
0062:        import java.util.logging.Level;
0063:        import org.netbeans.modules.cnd.apt.support.APTLanguageFilter;
0064:        import org.netbeans.modules.cnd.apt.support.APTLanguageSupport;
0065:        import org.netbeans.modules.cnd.modelimpl.cache.CacheManager;
0066:        import org.netbeans.modules.cnd.modelimpl.cache.FileCache;
0067:        import org.netbeans.modules.cnd.modelimpl.cache.impl.FileCacheImpl;
0068:        import org.netbeans.modules.cnd.modelimpl.csm.*;
0069:        import javax.swing.event.ChangeListener;
0070:        import org.netbeans.modules.cnd.api.model.util.CsmKindUtilities;
0071:        import org.netbeans.modules.cnd.api.project.NativeFileItem;
0072:        import org.netbeans.modules.cnd.apt.structure.APTFile;
0073:        import org.netbeans.modules.cnd.apt.support.APTDriver;
0074:        import org.netbeans.modules.cnd.apt.support.APTPreprocHandler;
0075:        import org.netbeans.modules.cnd.apt.support.APTToken;
0076:        import org.netbeans.modules.cnd.apt.support.StartEntry;
0077:        import org.netbeans.modules.cnd.apt.utils.APTUtils;
0078:        import org.netbeans.modules.cnd.modelimpl.debug.DiagnosticExceptoins;
0079:        import org.netbeans.modules.cnd.modelimpl.parser.apt.APTParseFileWalker;
0080:        import org.netbeans.modules.cnd.modelimpl.parser.apt.GuardBlockWalker;
0081:        import org.netbeans.modules.cnd.modelimpl.parser.generated.CPPTokenTypes;
0082:        import org.netbeans.modules.cnd.modelimpl.platform.ModelSupport;
0083:        import org.netbeans.modules.cnd.modelimpl.repository.PersistentUtils;
0084:        import org.netbeans.modules.cnd.modelimpl.repository.RepositoryUtils;
0085:        import org.netbeans.modules.cnd.modelimpl.textcache.NameCache;
0086:        import org.netbeans.modules.cnd.modelimpl.uid.LazyCsmCollection;
0087:        import org.netbeans.modules.cnd.modelimpl.uid.UIDCsmConverter;
0088:        import org.netbeans.modules.cnd.modelimpl.uid.UIDObjectFactory;
0089:        import org.netbeans.modules.cnd.modelimpl.uid.UIDUtilities;
0090:        import org.netbeans.modules.cnd.repository.spi.Persistent;
0091:        import org.netbeans.modules.cnd.repository.support.SelfPersistent;
0092:        import org.netbeans.modules.cnd.utils.cache.CharSequenceKey;
0093:
0094:        /**
0095:         * CsmFile implementations
0096:         * @author Vladimir Kvashin
0097:         */
0098:        public class FileImpl implements  CsmFile, MutableDeclarationsContainer,
0099:                ChangeListener, Disposable, Persistent, SelfPersistent {
0100:
0101:            public static final boolean reportErrors = TraceFlags.REPORT_PARSING_ERRORS
0102:                    | TraceFlags.DEBUG;
0103:            private static final boolean reportParse = Boolean
0104:                    .getBoolean("parser.log.parse");
0105:
0106:            private static final boolean emptyAstStatictics = Boolean
0107:                    .getBoolean("parser.empty.ast.statistics");
0108:
0109:            private static final boolean SKIP_UNNECESSARY_FAKE_FIXES = false;
0110:
0111:            public static final int UNDEFINED_FILE = 0;
0112:            public static final int SOURCE_FILE = 1;
0113:            public static final int SOURCE_C_FILE = 2;
0114:            public static final int SOURCE_CPP_FILE = 3;
0115:            public static final int HEADER_FILE = 4;
0116:
0117:            private FileBuffer fileBuffer;
0118:
0119:            // only one of project/projectUID must be used (based on USE_UID_TO_CONTAINER)  
0120:            private/*final*/ProjectBase projectRef;// can be set in onDispose or contstructor only
0121:            private final CsmUID<CsmProject> projectUID;
0122:
0123:            /** 
0124:             * It's a map since we need to eliminate duplications 
0125:             */
0126:            private Map<SortedKey, CsmUID<CsmOffsetableDeclaration>> declarations = new TreeMap<SortedKey, CsmUID<CsmOffsetableDeclaration>>();
0127:            private ReadWriteLock declarationsLock = new ReentrantReadWriteLock();
0128:
0129:            private Set<CsmUID<CsmInclude>> includes = createIncludes();
0130:            private ReadWriteLock includesLock = new ReentrantReadWriteLock();
0131:
0132:            private Set<CsmUID<CsmMacro>> macros = createMacros();
0133:            private ReadWriteLock macrosLock = new ReentrantReadWriteLock();
0134:
0135:            private int errorCount = 0;
0136:
0137:            private enum State {
0138:                INITIAL, PARSED, MODIFIED, BEING_PARSED
0139:            }
0140:
0141:            private State state;
0142:
0143:            private int fileType = UNDEFINED_FILE;
0144:
0145:            private Object stateLock = new Object();
0146:
0147:            private Collection<FunctionImplEx> fakeRegistrationsOLD = new ArrayList<FunctionImplEx>();
0148:            private Collection<CsmUID<FunctionImplEx>> fakeRegistrationUIDs = new CopyOnWriteArrayList<CsmUID<FunctionImplEx>>();
0149:
0150:            // TODO: move this field and correspondent logic to FileContainer.MyFile
0151:            private final GuardBlockState guardState;
0152:
0153:            private long lastParsed = Long.MIN_VALUE;
0154:
0155:            /** Cache the hash code */
0156:            private int hash; // Default to 0
0157:
0158:            /** 
0159:             * Stores the UIDs of the static functions declarations (not definitions) 
0160:             * This is necessary for finding definitions/declarations 
0161:             * since file-level static functions (i.e. c-style static functions) aren't registered in project
0162:             */
0163:            private Collection<CsmUID<CsmFunction>> staticFunctionDeclarationUIDs;
0164:
0165:            /** For test purposes only */
0166:            public interface Hook {
0167:                void parsingFinished(CsmFile file,
0168:                        APTPreprocHandler preprocHandler);
0169:            }
0170:
0171:            private static Hook hook = null;
0172:
0173:            public FileImpl(FileBuffer fileBuffer, ProjectBase project,
0174:                    int fileType, NativeFileItem nativeFileItem) {
0175:                state = State.INITIAL;
0176:                setBuffer(fileBuffer);
0177:                this .projectUID = UIDCsmConverter.projectToUID(project);
0178:                this .projectRef = null;
0179:                this .fileType = fileType;
0180:                this .guardState = new GuardBlockState();
0181:                if (nativeFileItem != null) {
0182:                    project.putNativeFileItem(getUID(), nativeFileItem);
0183:                }
0184:                Notificator.instance().registerNewFile(this );
0185:            }
0186:
0187:            /** For test purposes only */
0188:            public static void setHook(Hook aHook) {
0189:                hook = aHook;
0190:            }
0191:
0192:            public final NativeFileItem getNativeFileItem() {
0193:                return getProjectImpl().getNativeFileItem(getUID());
0194:            }
0195:
0196:            private ProjectBase _getProject(boolean assertNotNull) {
0197:                ProjectBase prj = this .projectRef;
0198:                if (prj == null) {
0199:                    prj = (ProjectBase) UIDCsmConverter
0200:                            .UIDtoProject(this .projectUID);
0201:                    if (assertNotNull) {
0202:                        assert (prj != null || this .projectUID == null) : "empty project for UID "
0203:                                + this .projectUID;
0204:                    }
0205:                }
0206:                return prj;
0207:            }
0208:
0209:            public boolean isSourceFile() {
0210:                return fileType == SOURCE_FILE || fileType == SOURCE_C_FILE
0211:                        || fileType == SOURCE_CPP_FILE;
0212:            }
0213:
0214:            public boolean isCppFile() {
0215:                return fileType == SOURCE_CPP_FILE;
0216:            }
0217:
0218:            /*package local*/void setSourceFile() {
0219:                if (!(fileType == SOURCE_C_FILE || fileType == SOURCE_CPP_FILE)) {
0220:                    fileType = SOURCE_FILE;
0221:                }
0222:            }
0223:
0224:            public boolean isHeaderFile() {
0225:                return fileType == HEADER_FILE;
0226:            }
0227:
0228:            /*package local*/void setHeaderFile() {
0229:                if (fileType == UNDEFINED_FILE) {
0230:                    fileType = HEADER_FILE;
0231:                }
0232:            }
0233:
0234:            // TODO: consider using macro map and __cplusplus here instead of just checking file name
0235:            public APTLanguageFilter getLanguageFilter() {
0236:                String lang = APTLanguageSupport.GNU_CPP;
0237:                String name = getName().toString();
0238:
0239:                if (name.length() > 2 && name.endsWith(".c")) { // NOI18N
0240:                    lang = APTLanguageSupport.GNU_C;
0241:                }
0242:
0243:                return APTLanguageSupport.getInstance().getFilter(lang);
0244:            }
0245:
0246:            public APTPreprocHandler getPreprocHandler() {
0247:                return getProjectImpl() == null ? null : getProjectImpl()
0248:                        .getPreprocHandler(fileBuffer.getFile());
0249:            }
0250:
0251:            public void setBuffer(FileBuffer fileBuffer) {
0252:                synchronized (changeStateLock) {
0253:                    if (this .fileBuffer != null) {
0254:                        this .fileBuffer.removeChangeListener(this );
0255:                    }
0256:                    this .fileBuffer = fileBuffer;
0257:                    if (state != State.INITIAL) {
0258:                        state = State.MODIFIED;
0259:                    }
0260:                    this .fileBuffer.addChangeListener(this );
0261:                }
0262:            }
0263:
0264:            public FileBuffer getBuffer() {
0265:                return this .fileBuffer;
0266:            }
0267:
0268:            public void ensureParsed(APTPreprocHandler preprocHandler) {
0269:                synchronized (stateLock) {
0270:                    switch (state) {
0271:                    case INITIAL:
0272:                        parse(preprocHandler);
0273:                        if (TraceFlags.DUMP_PARSE_RESULTS)
0274:                            new CsmTracer().dumpModel(this );
0275:                        break;
0276:                    case MODIFIED:
0277:                        reparse(preprocHandler);
0278:                        if (TraceFlags.DUMP_PARSE_RESULTS
0279:                                || TraceFlags.DUMP_REPARSE_RESULTS)
0280:                            new CsmTracer().dumpModel(this );
0281:                        break;
0282:                    case PARSED:
0283:                        break;
0284:                    }
0285:                }
0286:            }
0287:
0288:            public boolean validate() {
0289:                synchronized (changeStateLock) {
0290:                    if (state == State.PARSED) {
0291:                        long lastModified = getBuffer().lastModified();
0292:                        if (lastModified > lastParsed) {
0293:                            if (TraceFlags.TRACE_VALIDATION)
0294:                                System.err
0295:                                        .printf(
0296:                                                "VALIDATED %s\n\t lastModified=%d\n\t   lastParsed=%d\n",
0297:                                                getAbsolutePath(),
0298:                                                lastModified, lastParsed);
0299:                            state = State.MODIFIED;
0300:                            return false;
0301:                        }
0302:                    }
0303:                    return true;
0304:                }
0305:            }
0306:
0307:            private Object changeStateLock = new Object();
0308:
0309:            public void stateChanged(javax.swing.event.ChangeEvent e) {
0310:                stateChanged(false);
0311:            }
0312:
0313:            public void stateChanged(boolean invalidateCache) {
0314:                synchronized (changeStateLock) {
0315:                    if (state != State.INITIAL) {
0316:                        state = State.MODIFIED;
0317:                    }
0318:                    if (invalidateCache) {
0319:                        synchronized (tokStreamLock) {
0320:                            ref = null;
0321:                        }
0322:                        if (TraceFlags.USE_AST_CACHE) {
0323:                            CacheManager.getInstance().invalidate(this );
0324:                        } else {
0325:                            APTDriver.getInstance().invalidateAPT(
0326:                                    this .getBuffer());
0327:                        }
0328:                    }
0329:                }
0330:            }
0331:
0332:            public int getErrorCount() {
0333:                return errorCount;
0334:            }
0335:
0336:            /** 
0337:             * sometimes called externally
0338:             * by some (cached) project implementations, etc
0339:             */
0340:            public void render(AST tree) {
0341:                new AstRenderer(this ).render(tree);
0342:            }
0343:
0344:            /**
0345:             * Removes old content from te file and model,
0346:             * then parses the current buffer
0347:             */
0348:            public void reparse(APTPreprocHandler preprocHandler) {
0349:                synchronized (stateLock) {
0350:                    state = State.BEING_PARSED;
0351:                    try {
0352:                        _reparse((preprocHandler == null) ? getPreprocHandler()
0353:                                : preprocHandler);
0354:                    } finally {
0355:                        synchronized (changeStateLock) {
0356:                            if (state != State.MODIFIED) {
0357:                                state = State.PARSED;
0358:                            }
0359:                        }
0360:                        stateLock.notifyAll();
0361:                    }
0362:                }
0363:            }
0364:
0365:            private void _reparse(APTPreprocHandler preprocHandler) {
0366:                if (!ParserThreadManager.instance().isParserThread()
0367:                        && !ParserThreadManager.instance().isStandalone()) {
0368:                    String text = "Reparsing should be done only in a special Code Model Thread!!!"; // NOI18N
0369:                    Diagnostic.trace(text);
0370:                    new Throwable(text).printStackTrace(System.err);
0371:                }
0372:                if (TraceFlags.DEBUG)
0373:                    Diagnostic.trace("------ reparsing "
0374:                            + fileBuffer.getFile().getName()); // NOI18N
0375:                //Notificator.instance().startTransaction();
0376:                try {
0377:                    _clearIncludes();
0378:                    _clearMacros();
0379:                    AST ast = doParse(preprocHandler);
0380:                    if (ast != null) {
0381:                        disposeAll(false);
0382:                        render(ast);
0383:                    } else {
0384:                        //System.err.println("null ast for file " + getAbsolutePath());
0385:                    }
0386:                } finally {
0387:                    //Notificator.instance().endTransaction();
0388:                    // update this file and it's project     
0389:                    RepositoryUtils.put(this );
0390:                    if (TraceFlags.USE_DEEP_REPARSING) {
0391:                        getProjectImpl().getGraph().putFile(this );
0392:                    }
0393:                    Notificator.instance().registerChangedFile(this );
0394:                    Notificator.instance().flush();
0395:                }
0396:
0397:            }
0398:
0399:            public void dispose() {
0400:                onDispose();
0401:                Notificator.instance().registerRemovedFile(this );
0402:                disposeAll(true);
0403:            }
0404:
0405:            public void onProjectDispose() {
0406:                onDispose();
0407:            }
0408:
0409:            private void onDispose() {
0410:                if (TraceFlags.RESTORE_CONTAINER_FROM_UID) {
0411:                    // restore container from it's UID
0412:                    this .projectRef = (ProjectBase) UIDCsmConverter
0413:                            .UIDtoProject(this .projectUID);
0414:                    assert (this .projectRef != null || this .projectUID == null) : "empty project for UID "
0415:                            + this .projectUID;
0416:                }
0417:            }
0418:
0419:            private void disposeAll(boolean clearNonDisposable) {
0420:                //NB: we're copying declarations, because dispose can invoke this.removeDeclaration
0421:                //for( Iterator iter = declarations.values().iterator(); iter.hasNext(); ) {
0422:                Collection<CsmUID<CsmOffsetableDeclaration>> uids;
0423:                try {
0424:                    declarationsLock.writeLock().lock();
0425:                    uids = declarations.values();
0426:                    declarations = new TreeMap<SortedKey, CsmUID<CsmOffsetableDeclaration>>();
0427:                } finally {
0428:                    declarationsLock.writeLock().unlock();
0429:                }
0430:
0431:                if (clearNonDisposable) {
0432:                    _clearIncludes();
0433:                    _clearMacros();
0434:                }
0435:                Collection<CsmOffsetableDeclaration> arr = UIDCsmConverter
0436:                        .UIDsToDeclarations(uids);
0437:                Utils.disposeAll(arr);
0438:                RepositoryUtils.remove(uids);
0439:            }
0440:
0441:            private void _clearMacros() {
0442:                Set<CsmUID<CsmMacro>> copy = macros;
0443:                macros = createMacros();
0444:                RepositoryUtils.remove(copy);
0445:            }
0446:
0447:            private Set<CsmUID<CsmMacro>> createMacros() {
0448:                return new TreeSet<CsmUID<CsmMacro>>(
0449:                        UID_START_OFFSET_COMPARATOR);
0450:            }
0451:
0452:            private void _clearIncludes() {
0453:                try {
0454:                    includesLock.writeLock().lock();
0455:                    RepositoryUtils.remove(includes);
0456:                    includes = createIncludes();
0457:                } finally {
0458:                    includesLock.writeLock().unlock();
0459:                }
0460:            }
0461:
0462:            private Set<CsmUID<CsmInclude>> createIncludes() {
0463:                return new TreeSet<CsmUID<CsmInclude>>(
0464:                        UID_START_OFFSET_COMPARATOR);
0465:            }
0466:
0467:            public AST parse(APTPreprocHandler preprocHandler) {
0468:                synchronized (stateLock) {
0469:                    state = State.BEING_PARSED;
0470:                    try {
0471:                        return _parse((preprocHandler == null) ? getPreprocHandler()
0472:                                : preprocHandler);
0473:                    } finally {
0474:                        synchronized (changeStateLock) {
0475:                            if (state != State.MODIFIED) {
0476:                                state = State.PARSED;
0477:                            }
0478:                        }
0479:                        stateLock.notifyAll();
0480:                    }
0481:                }
0482:            }
0483:
0484:            private AST _parse(APTPreprocHandler preprocHandler) {
0485:
0486:                if (reportErrors) {
0487:                    if (!ParserThreadManager.instance().isParserThread()
0488:                            && !ParserThreadManager.instance().isStandalone()) {
0489:                        String text = "Reparsing should be done only in a special Code Model Thread!!!"; // NOI18N
0490:                        Diagnostic.trace(text);
0491:                        new Throwable(text).printStackTrace(System.err);
0492:                    }
0493:                }
0494:
0495:                Diagnostic.StopWatch sw = TraceFlags.TIMING_PARSE_PER_FILE_DEEP ? new Diagnostic.StopWatch()
0496:                        : null;
0497:
0498:                try {
0499:                    AST ast = doParse((preprocHandler == null) ? getPreprocHandler()
0500:                            : preprocHandler);
0501:                    if (TraceFlags.TIMING_PARSE_PER_FILE_DEEP)
0502:                        sw.stopAndReport("Parsing of "
0503:                                + fileBuffer.getFile().getName() + " took \t"); // NOI18N
0504:
0505:                    if (ast != null) {
0506:                        Diagnostic.StopWatch sw2 = TraceFlags.TIMING_PARSE_PER_FILE_DEEP ? new Diagnostic.StopWatch()
0507:                                : null;
0508:                        //Notificator.instance().startTransaction();
0509:                        if (isValid()) { // FIXUP: use a special lock here
0510:                            render(ast);
0511:                            if (TraceFlags.TIMING_PARSE_PER_FILE_DEEP)
0512:                                sw2.stopAndReport("Rendering of "
0513:                                        + fileBuffer.getFile().getName()
0514:                                        + " took \t"); // NOI18N
0515:                        }
0516:                        return ast;
0517:                    }
0518:                } finally {
0519:                    if (isValid()) { // FIXUP: use a special lock here
0520:                        RepositoryUtils.put(this );
0521:                    }
0522:                    if (TraceFlags.USE_DEEP_REPARSING && isValid()) { // FIXUP: use a special lock here
0523:                        getProjectImpl().getGraph().putFile(this );
0524:                    }
0525:                    if (isValid()) { // FIXUP: use a special lock here
0526:                        Notificator.instance().registerChangedFile(this );
0527:                        Notificator.instance().flush();
0528:                    } else {
0529:                        // FIXUP: there should be a notificator per project instead!
0530:                        Notificator.instance().reset();
0531:                    }
0532:                }
0533:                return null;
0534:            }
0535:
0536:            private TokenStream createFullTokenStream() {
0537:                APTPreprocHandler preprocHandler = getPreprocHandler();
0538:                APTFile apt = null;
0539:                if (TraceFlags.USE_AST_CACHE) {
0540:                    apt = CacheManager.getInstance().findAPT(this );
0541:                } else {
0542:                    try {
0543:                        apt = APTDriver.getInstance().findAPT(fileBuffer);
0544:                    } catch (IOException ex) {
0545:                        DiagnosticExceptoins.register(ex);
0546:                    }
0547:                }
0548:                if (apt == null) {
0549:                    return null;
0550:                }
0551:                ProjectBase startProject = ProjectBase
0552:                        .getStartProject(preprocHandler.getState());
0553:                if (startProject == null) {
0554:                    System.err.println(" null project for "
0555:                            + APTHandlersSupport
0556:                                    .extractStartEntry(preprocHandler
0557:                                            .getState())
0558:                            + // NOI18N
0559:                            "\n while getting TS of file " + getAbsolutePath()
0560:                            + "\n of project " + getProject()); // NOI18N
0561:                    return null;
0562:                }
0563:                APTParseFileWalker walker = new APTParseFileWalker(
0564:                        startProject, apt, this , preprocHandler);
0565:                return walker.getFilteredTokenStream(getLanguageFilter());
0566:            }
0567:
0568:            private final String tokStreamLock = new String("TokenStream lock");
0569:            private Reference<OffsetTokenStream> ref = new SoftReference(null);
0570:
0571:            public TokenStream getTokenStream(int startOffset, int endOffset) {
0572:                try {
0573:                    OffsetTokenStream stream;
0574:                    synchronized (tokStreamLock) {
0575:                        stream = ref != null ? ref.get() : null;
0576:                        ref = new SoftReference(null);
0577:                    }
0578:                    if (stream == null || stream.getStartOffset() > startOffset) {
0579:                        if (stream == null) {
0580:                            //                    System.err.println("new stream created for " + startOffset);
0581:                        } else {
0582:                            //                    System.err.println("new stream created, because prev stream was finished on " + stream.getStartOffset() + " now asked for " + startOffset);
0583:                        }
0584:                        stream = new OffsetTokenStream(createFullTokenStream());
0585:                    } else {
0586:                        //                System.err.println("use cached stream finished previously on " + stream.getStartOffset() + " now asked for " + startOffset);
0587:                    }
0588:                    stream.moveTo(startOffset, endOffset);
0589:                    return stream;
0590:                } catch (TokenStreamException ex) {
0591:                    Utils.LOG.severe("Can't create compound statement: "
0592:                            + ex.getMessage());
0593:                    DiagnosticExceptoins.register(ex);
0594:                    return null;
0595:                }
0596:            }
0597:
0598:            public void releaseTokenStream(TokenStream ts) {
0599:                if (ts instanceof  OffsetTokenStream) {
0600:                    OffsetTokenStream offsTS = (OffsetTokenStream) ts;
0601:                    synchronized (tokStreamLock) {
0602:                        if (ref != null && ref.get() == null) {
0603:                            ref = new SoftReference<OffsetTokenStream>(offsTS);
0604:                            //                    System.err.println("caching stream finished on " + offsTS.getStartOffset());                    
0605:                        }
0606:                    }
0607:                }
0608:            }
0609:
0610:            private static class OffsetTokenStream implements  TokenStream {
0611:
0612:                private final TokenStream stream;
0613:                private Token next;
0614:                private int endOffset;
0615:
0616:                public OffsetTokenStream(TokenStream stream) {
0617:                    this .stream = stream;
0618:                }
0619:
0620:                public Token nextToken() throws TokenStreamException {
0621:                    Token out = next;
0622:
0623:                    if (out == null || out.getType() == CPPTokenTypes.EOF
0624:                            || (((APTToken) out).getOffset() > endOffset)) {
0625:                        out = APTUtils.EOF_TOKEN;
0626:                    } else {
0627:                        next = stream.nextToken();
0628:                    }
0629:                    return out;
0630:                }
0631:
0632:                public int getStartOffset() {
0633:                    return next == null
0634:                            || (next.getType() == CPPTokenTypes.EOF) ? Integer.MAX_VALUE
0635:                            : ((APTToken) next).getOffset();
0636:                }
0637:
0638:                public void moveTo(int startOffset, int endOffset)
0639:                        throws TokenStreamException {
0640:                    this .endOffset = endOffset;
0641:                    assert this .endOffset >= startOffset;
0642:                    for (next = stream.nextToken(); next != null
0643:                            && next.getType() != CPPTokenTypes.EOF; next = stream
0644:                            .nextToken()) {
0645:                        assert (next instanceof  APTToken) : "we have only APTTokens in token stream";
0646:                        int currOffset = ((APTToken) next).getOffset();
0647:                        if (currOffset == startOffset) {
0648:                            break;
0649:                        }
0650:                    }
0651:                }
0652:            };
0653:
0654:            private AST doParse(APTPreprocHandler preprocHandler) {
0655:                //        if( "cursor.hpp".equals(fileBuffer.getFile().getName()) ) {
0656:                //            System.err.println("cursor.hpp");
0657:                //        }  
0658:                if (reportParse || TraceFlags.DEBUG) {
0659:                    System.err.println("# APT-based AST-cached Parsing "
0660:                            + fileBuffer.getFile().getPath() + " (Thread="
0661:                            + Thread.currentThread().getName() + ')');
0662:                }
0663:
0664:                int flags = CPPParserEx.CPP_CPLUSPLUS;
0665:                if (!reportErrors) {
0666:                    flags |= CPPParserEx.CPP_SUPPRESS_ERRORS;
0667:                }
0668:
0669:                APTPreprocHandler.State oldState = preprocHandler.getState();
0670:
0671:                // 1. get cache with AST
0672:                // 2a if cache has AST => use AST and APTLight
0673:                // 2b otherwise if cache has APT full => use APT full to generate parser's
0674:                //     token stream and save in cache
0675:                AST ast = null;
0676:                APTFile aptLight = null;
0677:                APTFile aptFull = null;
0678:                if (TraceFlags.USE_AST_CACHE) {
0679:                    FileCache cacheWithAST = CacheManager.getInstance()
0680:                            .findCacheWithAST(this , preprocHandler);
0681:                    assert (cacheWithAST != null);
0682:                    ast = cacheWithAST.getAST(preprocHandler);
0683:                    aptLight = cacheWithAST.getAPTLight();
0684:                    aptFull = cacheWithAST.getAPT();
0685:                } else {
0686:                    try {
0687:                        aptFull = APTDriver.getInstance().findAPT(
0688:                                this .getBuffer());
0689:                    } catch (FileNotFoundException ex) {
0690:                        APTUtils.LOG.log(Level.WARNING,
0691:                                "FileImpl: file {0} not found",
0692:                                new Object[] { getBuffer().getFile()
0693:                                        .getAbsolutePath() });// NOI18N
0694:                        DiagnosticExceptoins.register(ex);
0695:                    } catch (IOException ex) {
0696:                        DiagnosticExceptoins.register(ex);
0697:                    }
0698:                }
0699:                if (ast != null) {
0700:                    if (TraceFlags.TRACE_CACHE) {
0701:                        System.err
0702:                                .println("CACHE: parsing using AST and APTLight for "
0703:                                        + getAbsolutePath());
0704:                    }
0705:                    // use light for visiting and return ast as result
0706:                    assert (aptLight != null);
0707:                    boolean skip = TraceFlags.CACHE_SKIP_APT_VISIT;
0708:                    if (!skip) {
0709:                        APTParseFileWalker walker = new APTParseFileWalker(
0710:                                ProjectBase.getStartProject(preprocHandler
0711:                                        .getState()), aptLight, this ,
0712:                                preprocHandler);
0713:                        walker.addMacroAndIncludes(true);
0714:                        walker.visit();
0715:                    } else {
0716:                        if (TraceFlags.TRACE_CACHE) {
0717:                            System.err
0718:                                    .println("CACHE: skipped APTLight visiting");
0719:                        }
0720:                    }
0721:                } else if (aptFull != null) {
0722:                    // use full APT for generating token stream
0723:                    if (TraceFlags.TRACE_CACHE) {
0724:                        System.err.println("CACHE: parsing using full APT for "
0725:                                + getAbsolutePath());
0726:                    }
0727:                    // set guard info
0728:                    updateGuardAfterParse(preprocHandler, aptFull);
0729:                    // make real parse
0730:                    ProjectBase startProject = ProjectBase
0731:                            .getStartProject(preprocHandler.getState());
0732:                    if (startProject == null) {
0733:                        System.err.println(" null project for "
0734:                                + APTHandlersSupport
0735:                                        .extractStartEntry(preprocHandler
0736:                                                .getState())
0737:                                + // NOI18N
0738:                                "\n while parsing file " + getAbsolutePath()
0739:                                + "\n of project " + getProject()); // NOI18N
0740:                        return null;
0741:                    }
0742:                    APTParseFileWalker walker = new APTParseFileWalker(
0743:                            startProject, aptFull, this , preprocHandler);
0744:                    walker.addMacroAndIncludes(true);
0745:                    if (TraceFlags.DEBUG) {
0746:                        System.err.println("doParse " + getAbsolutePath()
0747:                                + " with "
0748:                                + ParserQueue.tracePreprocState(oldState));
0749:                    }
0750:                    CPPParserEx parser = CPPParserEx
0751:                            .getInstance(
0752:                                    fileBuffer.getFile().getName(),
0753:                                    walker
0754:                                            .getFilteredTokenStream(getLanguageFilter()),
0755:                                    flags);
0756:                    long time = (emptyAstStatictics) ? System
0757:                            .currentTimeMillis() : 0;
0758:                    try {
0759:                        parser.translation_unit();
0760:                    } catch (Error ex) {
0761:                        System.err.println(ex.getClass().getName()
0762:                                + " at parsing file "
0763:                                + fileBuffer.getFile().getAbsolutePath()); // NOI18N
0764:                        throw ex;
0765:                    }
0766:
0767:                    if (emptyAstStatictics) {
0768:                        time = System.currentTimeMillis() - time;
0769:                        System.err
0770:                                .println("PARSED FILE "
0771:                                        + getAbsolutePath()
0772:                                        + (AstUtil.isEmpty(parser.getAST(),
0773:                                                true) ? " EMPTY" : "") + ' '
0774:                                        + time + " ms");
0775:                    }
0776:                    if (TraceFlags.DUMP_AST) {
0777:                        System.err.println("\n");
0778:                        System.err.print("AST: ");
0779:                        System.err.print(getAbsolutePath());
0780:                        System.err.print(' ');
0781:                        AstUtil.toStream(parser.getAST(), System.err);
0782:                        System.err.println("\n");
0783:
0784:                    }
0785:                    errorCount = parser.getErrorCount();
0786:                    ast = parser.getAST();
0787:                    // save all in cache
0788:                    if (state != State.MODIFIED) {
0789:                        if (TraceFlags.USE_AST_CACHE) {
0790:                            if (getBuffer().isFileBased()
0791:                                    && !TraceFlags.CACHE_SKIP_SAVE) {
0792:                                CacheManager.getInstance().saveCache(
0793:                                        this ,
0794:                                        new FileCacheImpl(aptLight, aptFull,
0795:                                                ast));
0796:                            } else {
0797:                                if (TraceFlags.TRACE_CACHE) {
0798:                                    System.err
0799:                                            .println("CACHE: not save cache for document based file "
0800:                                                    + getAbsolutePath());
0801:                                }
0802:                            }
0803:                        }
0804:                    } else {
0805:                        ast = null;
0806:                        if (TraceFlags.TRACE_CACHE) {
0807:                            System.err
0808:                                    .println("CACHE: not save cache for file modified during parsing"
0809:                                            + getAbsolutePath());
0810:                        }
0811:                    }
0812:                }
0813:                lastParsed = Math.max(System.currentTimeMillis(), fileBuffer
0814:                        .lastModified());
0815:                if (TraceFlags.TRACE_VALIDATION)
0816:                    System.err
0817:                            .printf(
0818:                                    "PARSED    %s \n\tlastModified=%d\n\t  lastParsed=%d  diff=%d\n",
0819:                                    getAbsolutePath(), fileBuffer
0820:                                            .lastModified(), lastParsed,
0821:                                    fileBuffer.lastModified() - lastParsed);
0822:                Hook aHook = hook;
0823:                if (aHook != null) {
0824:                    aHook.parsingFinished(this , preprocHandler);
0825:                }
0826:                return ast;
0827:            }
0828:
0829:            /*package*/void initGuardIfNeeded(
0830:                    APTPreprocHandler preprocHandler, APTFile apt) {
0831:                if (!getGuardState().isInited()) {
0832:                    setGuardState(preprocHandler, apt);
0833:                }
0834:            }
0835:
0836:            private void updateGuardAfterParse(
0837:                    APTPreprocHandler preprocHandler, APTFile apt) {
0838:                if (!getGuardState().isInited()) {
0839:                    setGuardState(preprocHandler, apt);
0840:                } else {
0841:                    getGuardState().setGuardBlockState(preprocHandler,
0842:                            getGuardState().getGuard());
0843:                }
0844:            }
0845:
0846:            private void setGuardState(APTPreprocHandler preprocHandler,
0847:                    APTFile aptLight) {
0848:                synchronized (getGuardState()) {
0849:                    GuardBlockWalker guard = new GuardBlockWalker(aptLight,
0850:                            preprocHandler);
0851:                    TokenStream ts = guard.getTokenStream();
0852:                    try {
0853:                        Token token = ts.nextToken();
0854:                        while (!APTUtils.isEOF(token)) {
0855:                            if (!APTUtils.isCommentToken(token)) {
0856:                                guard.clearGuard();
0857:                                break;
0858:                            }
0859:                            token = ts.nextToken();
0860:                        }
0861:                    } catch (TokenStreamException ex) {
0862:                        guard.clearGuard();
0863:                    }
0864:                    getGuardState().setGuardBlockState(preprocHandler,
0865:                            guard.getGuard());
0866:                }
0867:            }
0868:
0869:            public void addInclude(IncludeImpl includeImpl) {
0870:                CsmUID<CsmInclude> inclUID = RepositoryUtils.put(includeImpl);
0871:                assert inclUID != null;
0872:                try {
0873:                    includesLock.writeLock().lock();
0874:                    includes.add(inclUID);
0875:                } finally {
0876:                    includesLock.writeLock().unlock();
0877:                }
0878:            }
0879:
0880:            public static final Comparator<CsmOffsetable> START_OFFSET_COMPARATOR = new Comparator<CsmOffsetable>() {
0881:                public int compare(CsmOffsetable o1, CsmOffsetable o2) {
0882:                    if (o1 == o2) {
0883:                        return 0;
0884:                    }
0885:                    int ofs1 = o1.getStartOffset();
0886:                    int ofs2 = o2.getStartOffset();
0887:                    if (ofs1 == ofs2) {
0888:                        return 0;
0889:                    } else {
0890:                        return (ofs1 - ofs2);
0891:                    }
0892:                }
0893:
0894:                public @Override
0895:                boolean equals(Object obj) {
0896:                    return super .equals(obj);
0897:                }
0898:
0899:                public @Override
0900:                int hashCode() {
0901:                    return 11; // any dummy value
0902:                }
0903:            };
0904:
0905:            static final private Comparator<CsmUID> UID_START_OFFSET_COMPARATOR = new Comparator<CsmUID>() {
0906:                public int compare(CsmUID o1, CsmUID o2) {
0907:                    if (o1 == o2) {
0908:                        return 0;
0909:                    }
0910:                    Comparable<CsmUID> i1 = (Comparable<CsmUID>) o1;
0911:                    assert i1 != null;
0912:                    return i1.compareTo(o2);
0913:                }
0914:
0915:                public @Override
0916:                boolean equals(Object obj) {
0917:                    return super .equals(obj);
0918:                }
0919:
0920:                public @Override
0921:                int hashCode() {
0922:                    return 11; // any dummy value
0923:                }
0924:            };
0925:
0926:            public String getText(int start, int end) {
0927:                try {
0928:                    return fileBuffer.getText(start, end);
0929:                } catch (IOException e) {
0930:                    DiagnosticExceptoins.register(e);
0931:                    return "";
0932:                }
0933:            }
0934:
0935:            public String getText() {
0936:                try {
0937:                    return fileBuffer.getText();
0938:                } catch (IOException e) {
0939:                    DiagnosticExceptoins.register(e);
0940:                    return "";
0941:                }
0942:            }
0943:
0944:            public CsmProject getProject() {
0945:                return _getProject(true);
0946:            }
0947:
0948:            /** Just a convenient shortcut to eliminate casts */
0949:            public ProjectBase getProjectImpl() {
0950:                return _getProject(true);
0951:            }
0952:
0953:            public CharSequence getName() {
0954:                return CharSequenceKey.create(fileBuffer.getFile().getName());
0955:            }
0956:
0957:            public Collection<CsmInclude> getIncludes() {
0958:                Collection<CsmInclude> out;
0959:                try {
0960:                    includesLock.readLock().lock();
0961:                    out = UIDCsmConverter.UIDsToIncludes(includes);
0962:                } finally {
0963:                    includesLock.readLock().unlock();
0964:                }
0965:                return out;
0966:            }
0967:
0968:            public Collection<CsmOffsetableDeclaration> getDeclarations() {
0969:                if (!SKIP_UNNECESSARY_FAKE_FIXES) {
0970:                    fixFakeRegistrations();
0971:                }
0972:                Collection<CsmOffsetableDeclaration> decls;
0973:                try {
0974:                    declarationsLock.readLock().lock();
0975:                    Collection<CsmUID<CsmOffsetableDeclaration>> uids = declarations
0976:                            .values();
0977:                    decls = UIDCsmConverter.UIDsToDeclarations(uids);
0978:                } finally {
0979:                    declarationsLock.readLock().unlock();
0980:                }
0981:                return decls;
0982:            }
0983:
0984:            public void addMacro(CsmMacro macro) {
0985:                CsmUID<CsmMacro> macroUID = RepositoryUtils.put(macro);
0986:                assert macroUID != null;
0987:                try {
0988:                    macrosLock.writeLock().lock();
0989:                    macros.add(macroUID);
0990:                } finally {
0991:                    macrosLock.writeLock().unlock();
0992:                }
0993:            }
0994:
0995:            public Collection<CsmMacro> getMacros() {
0996:                Collection<CsmMacro> out;
0997:                try {
0998:                    macrosLock.readLock().lock();
0999:                    out = UIDCsmConverter.UIDsToMacros(macros);
1000:                } finally {
1001:                    macrosLock.readLock().unlock();
1002:                }
1003:                return out;
1004:            }
1005:
1006:            public void addDeclaration(CsmOffsetableDeclaration decl) {
1007:                CsmUID<CsmOffsetableDeclaration> uidDecl = RepositoryUtils
1008:                        .put(decl);
1009:                try {
1010:                    declarationsLock.writeLock().lock();
1011:                    declarations.put(getSortKey(decl), uidDecl);
1012:                } finally {
1013:                    declarationsLock.writeLock().unlock();
1014:                }
1015:                // TODO: remove this dirty hack!
1016:                if (decl instanceof  VariableImpl) {
1017:                    VariableImpl v = (VariableImpl) decl;
1018:                    if (isOfFileScope(v)) {
1019:                        v.setScope(this );
1020:                    }
1021:                }
1022:                if (CsmKindUtilities.isFunctionDeclaration(decl)) {
1023:                    FunctionImpl fi = (FunctionImpl) decl;
1024:                    if (fi.isStatic()) {
1025:                        addStaticFunctionDeclaration(fi);
1026:                    }
1027:                }
1028:            }
1029:
1030:            private void addStaticFunctionDeclaration(FunctionImpl func) {
1031:                if (staticFunctionDeclarationUIDs == null) {
1032:                    staticFunctionDeclarationUIDs = new ArrayList<CsmUID<CsmFunction>>();
1033:                }
1034:                staticFunctionDeclarationUIDs.add(func.getUID());
1035:            }
1036:
1037:            /** 
1038:             * Gets the list of the static functions declarations (not definitions) 
1039:             * This is necessary for finding definitions/declarations 
1040:             * since file-level static functions (i.e. c-style static functions) aren't registered in project
1041:             */
1042:            public Collection<CsmFunction> getStaticFunctionDeclarations() {
1043:                if (staticFunctionDeclarationUIDs == null) {
1044:                    return Collections.<CsmFunction> emptyList();
1045:                } else {
1046:                    return new LazyCsmCollection<CsmFunction>(
1047:                            new ArrayList<CsmUID<CsmFunction>>(
1048:                                    staticFunctionDeclarationUIDs), true);
1049:                }
1050:            }
1051:
1052:            public static boolean isOfFileScope(VariableImpl v) {
1053:                if (v.isStatic()) {
1054:                    return true;
1055:                } else if (v.isConst()) {
1056:                    if (!v.isExtern()) {
1057:                        return true;
1058:                    }
1059:                } else {
1060:                    return false;
1061:                    //	    if( ! v.isExtern() ) {
1062:                    //		return true;
1063:                    //	    }
1064:                }
1065:                return false;
1066:            }
1067:
1068:            public void removeDeclaration(CsmOffsetableDeclaration declaration) {
1069:                _removeDeclaration(declaration);
1070:            }
1071:
1072:            private void _removeDeclaration(CsmOffsetableDeclaration declaration) {
1073:                CsmUID<CsmOffsetableDeclaration> uidDecl;
1074:                try {
1075:                    declarationsLock.writeLock().lock();
1076:                    uidDecl = declarations.remove(getSortKey(declaration));
1077:                } finally {
1078:                    declarationsLock.writeLock().unlock();
1079:                }
1080:                RepositoryUtils.remove(uidDecl);
1081:                // update repository
1082:                RepositoryUtils.put(this );
1083:            }
1084:
1085:            private SortedKey getSortKey(CsmOffsetableDeclaration declaration) {
1086:                return new SortedKey(declaration);
1087:            }
1088:
1089:            public String getAbsolutePath() {
1090:                return fileBuffer.getFile().getAbsolutePath();
1091:            }
1092:
1093:            public File getFile() {
1094:                return fileBuffer.getFile();
1095:            }
1096:
1097:            public Collection<CsmScopeElement> getScopeElements() {
1098:                List<CsmScopeElement> l = new ArrayList<CsmScopeElement>();
1099:                //TODO: add static functions
1100:                for (Iterator iter = getDeclarations().iterator(); iter
1101:                        .hasNext();) {
1102:                    CsmDeclaration decl = (CsmDeclaration) iter.next();
1103:                    // TODO: remove this dirty hack!
1104:                    if (decl instanceof  VariableImpl) {
1105:                        VariableImpl v = (VariableImpl) decl;
1106:                        if (isOfFileScope(v)) {
1107:                            l.add(v);
1108:                        }
1109:                    }
1110:                }
1111:                return l;
1112:            }
1113:
1114:            public boolean isValid() {
1115:                CsmProject project = _getProject(false);
1116:                return project != null && project.isValid();
1117:            }
1118:
1119:            public boolean isParsed() {
1120:                synchronized (changeStateLock) {
1121:                    return state == State.PARSED;
1122:                }
1123:            }
1124:
1125:            public boolean isParsingOrParsed() {
1126:                synchronized (changeStateLock) {
1127:                    return state == State.PARSED || state == State.BEING_PARSED;
1128:                }
1129:            }
1130:
1131:            public void scheduleParsing(boolean wait)
1132:                    throws InterruptedException {
1133:                scheduleParsing(wait, null);
1134:            }
1135:
1136:            public void scheduleParsing(boolean wait,
1137:                    APTPreprocHandler.State ppState)
1138:                    throws InterruptedException {
1139:                //if( TraceFlags.TRACE_PARSER_QUEUE ) System.err.println("> File " + getName() + " @" + hashCode() + " waiting for parse; thread: " + Thread.currentThread().getName());
1140:                boolean fixFakes = false;
1141:                synchronized (stateLock) {
1142:                    //if( TraceFlags.TRACE_PARSER_QUEUE ) System.err.println("  sync " + getName() + " @" + hashCode() + " waiting for parse; thread: " + Thread.currentThread().getName());
1143:                    if (SKIP_UNNECESSARY_FAKE_FIXES) {
1144:                        if (isParsed()) {
1145:                            fixFakes = wait;
1146:                        } else {
1147:                            while (!isParsed()) {
1148:                                ParserQueue.instance().addFirst(this , ppState,
1149:                                        false);
1150:                                //if( TraceFlags.TRACE_PARSER_QUEUE ) System.err.println("  !prs " + getName() + " @" + hashCode() + " waiting for parse; thread: " + Thread.currentThread().getName());
1151:                                if (wait) {
1152:                                    stateLock.wait();
1153:                                } else {
1154:                                    return;
1155:                                }
1156:                                //if( TraceFlags.TRACE_PARSER_QUEUE ) System.err.println("< wait " + getName() + " @" + hashCode() + " waiting for parse; thread: " + Thread.currentThread().getName());
1157:                            }
1158:                        }
1159:                    } else {
1160:                        while (!isParsed()) {
1161:                            ParserQueue.instance().addFirst(this , ppState,
1162:                                    false);
1163:                            //if( TraceFlags.TRACE_PARSER_QUEUE ) System.err.println("  !prs " + getName() + " @" + hashCode() + " waiting for parse; thread: " + Thread.currentThread().getName());
1164:                            if (wait) {
1165:                                stateLock.wait();
1166:                            } else {
1167:                                return;
1168:                            }
1169:                            //if( TraceFlags.TRACE_PARSER_QUEUE ) System.err.println("< wait " + getName() + " @" + hashCode() + " waiting for parse; thread: " + Thread.currentThread().getName());
1170:                        }
1171:                    }
1172:                }
1173:                if (SKIP_UNNECESSARY_FAKE_FIXES && fixFakes) {
1174:                    fixFakeRegistrations();
1175:                }
1176:                //if( TraceFlags.TRACE_PARSER_QUEUE ) System.err.println("< File " + getName() + " @" + hashCode() + " waiting for parse; thread: " + Thread.currentThread().getName());
1177:            }
1178:
1179:            public void onFakeRegisration(FunctionImplEx decl) {
1180:                CsmUID<FunctionImplEx> uidDecl = UIDCsmConverter
1181:                        .declarationToUID(decl);
1182:                fakeRegistrationUIDs.add(uidDecl);
1183:            }
1184:
1185:            public void fixFakeRegistrations() {
1186:                if (!isValid()) {
1187:                    return;
1188:                }
1189:                Collection<FunctionImplEx> fakes = Collections
1190:                        .<FunctionImplEx> emptySet();
1191:
1192:                if (fakeRegistrationUIDs.size() > 0) {
1193:                    fakes = UIDCsmConverter
1194:                            .UIDsToDeclarationsUnsafe(fakeRegistrationUIDs);
1195:                    fakeRegistrationUIDs.clear();
1196:                }
1197:                for (FunctionImplEx curElem : fakes) {
1198:                    // Due to lazy list the client should check value on null.
1199:                    if (curElem != null) {
1200:                        curElem.fixFakeRegistration();
1201:                    }
1202:                }
1203:            }
1204:
1205:            public @Override
1206:            String toString() {
1207:                return "FileImpl @" + hashCode() + ' ' + getAbsolutePath(); // NOI18N
1208:            }
1209:
1210:            public CsmUID<CsmFile> getUID() {
1211:                if (uid == null) {
1212:                    uid = UIDUtilities.createFileUID(this );
1213:                }
1214:                return uid;
1215:            }
1216:
1217:            private CsmUID<CsmFile> uid = null;
1218:
1219:            ////////////////////////////////////////////////////////////////////////////
1220:            // impl of persistent
1221:
1222:            public void write(DataOutput output) throws IOException {
1223:                PersistentUtils.writeBuffer(this .fileBuffer, output);
1224:                UIDObjectFactory factory = UIDObjectFactory.getDefaultFactory();
1225:                try {
1226:                    declarationsLock.readLock().lock();
1227:                    factory.writeSortedStringToUIDMap(this .declarations,
1228:                            output, false);
1229:                } finally {
1230:                    declarationsLock.readLock().unlock();
1231:                }
1232:                try {
1233:                    includesLock.readLock().lock();
1234:                    factory.writeUIDCollection(this .includes, output, false);
1235:                } finally {
1236:                    includesLock.readLock().unlock();
1237:                }
1238:                try {
1239:                    macrosLock.readLock().lock();
1240:                    factory.writeUIDCollection(this .macros, output, false);
1241:                } finally {
1242:                    macrosLock.readLock().unlock();
1243:                }
1244:                factory.writeUIDCollection(this .fakeRegistrationUIDs, output,
1245:                        false);
1246:                //output.writeUTF(state.toString());
1247:                output.writeInt(fileType);
1248:
1249:                // not null UID
1250:                assert this .projectUID != null;
1251:                UIDObjectFactory.getDefaultFactory().writeUID(this .projectUID,
1252:                        output);
1253:                guardState.write(output);
1254:                output.writeLong(lastParsed);
1255:                output.writeUTF(state.toString());
1256:            }
1257:
1258:            public FileImpl(DataInput input) throws IOException {
1259:                this .fileBuffer = PersistentUtils.readBuffer(input);
1260:
1261:                UIDObjectFactory factory = UIDObjectFactory.getDefaultFactory();
1262:                factory
1263:                        .readSortedStringToUIDMap(this .declarations, input,
1264:                                null);
1265:                factory.readUIDCollection(this .includes, input);
1266:                factory.readUIDCollection(this .macros, input);
1267:                factory.readUIDCollection(this .fakeRegistrationUIDs, input);
1268:                //state = State.valueOf(input.readUTF());
1269:                fileType = input.readInt();
1270:
1271:                this .projectUID = UIDObjectFactory.getDefaultFactory().readUID(
1272:                        input);
1273:                // not null UID
1274:                assert this .projectUID != null;
1275:                this .projectRef = null;
1276:
1277:                assert fileBuffer != null;
1278:                assert fileBuffer.isFileBased();
1279:                guardState = new GuardBlockState(input);
1280:                lastParsed = input.readLong();
1281:                state = State.valueOf(input.readUTF());
1282:            }
1283:
1284:            public @Override
1285:            int hashCode() {
1286:                if (hash == 0) { // we don't need sync here - at worst, we'll calculate the same value twice
1287:                    String identityHashPath = getProjectImpl().getUniqueName()
1288:                            + "*" + getAbsolutePath(); // NOI18N
1289:                    hash = identityHashPath.hashCode();
1290:                }
1291:                return hash;
1292:            }
1293:
1294:            public @Override
1295:            boolean equals(Object obj) {
1296:                if (obj == null || !(obj instanceof  FileImpl)) {
1297:                    return false;
1298:                }
1299:                if (obj == this ) {
1300:                    return true;
1301:                }
1302:                FileImpl other = (FileImpl) obj;
1303:                if (this .getAbsolutePath().equals(other.getAbsolutePath())) {
1304:                    return this .getProjectImpl().getUniqueName().equals(
1305:                            other.getProjectImpl().getUniqueName());
1306:                }
1307:                return false;
1308:            }
1309:
1310:            private GuardBlockState getGuardState() {
1311:                return guardState;
1312:            }
1313:
1314:            // for tests only
1315:            public GuardBlockState testGetGuardState() {
1316:                return guardState;
1317:            }
1318:
1319:            public boolean isNeedReparse(APTPreprocHandler.State oldState,
1320:                    APTPreprocHandler newState) {
1321:                boolean update = false;
1322:                if (oldState == null || !oldState.isValid()) {
1323:                    update = true;
1324:                } else if (!oldState.isCompileContext()
1325:                        && newState.isCompileContext()) {
1326:                    update = true;
1327:                } else {
1328:                    update = getGuardState().isNeedReparse(newState);
1329:                }
1330:                return update;
1331:            }
1332:
1333:            public boolean isNeedReparse(APTPreprocHandler.State oldState,
1334:                    APTPreprocHandler.State preprocState) {
1335:                if (oldState == null || !oldState.isValid()) {
1336:                    return true;
1337:                } else if (oldState.isCompileContext()) {
1338:                    // do nothing
1339:                    if (preprocState != null
1340:                            && isNeedReparseGuardBlock(preprocState)) {
1341:                        // override state with new one
1342:                        return true;
1343:                    }
1344:                } else if (preprocState != null
1345:                        && preprocState.isCompileContext()) {
1346:                    // override state with new one
1347:                    return true;
1348:                }
1349:                return false;
1350:            }
1351:
1352:            private boolean isNeedReparseGuardBlock(
1353:                    APTPreprocHandler.State preprocState) {
1354:                StartEntry startEntry = new StartEntry(getAbsolutePath(),
1355:                        RepositoryUtils.UIDtoKey(getProject().getUID()));
1356:                APTPreprocHandler preprocHandler = APTHandlersSupport
1357:                        .createEmptyPreprocHandler(startEntry);
1358:                preprocHandler.setState(preprocState);
1359:                return getGuardState().isNeedReparse(preprocHandler);
1360:            }
1361:
1362:            public int getOffset(int line, int column) {
1363:                if (line <= 0 || column <= 0) {
1364:                    throw new IllegalArgumentException(
1365:                            "line and column are 1-based"); // NOI18N
1366:                }
1367:                int offset = 0;
1368:                int curLine = 1;
1369:                String text = getText();
1370:                // find line
1371:                for (; offset < text.length() && curLine < line; offset++) {
1372:                    if (text.charAt(offset) == '\n') {
1373:                        curLine++;
1374:                    }
1375:                }
1376:                // check line
1377:                if (curLine < line) {
1378:                    throw new IllegalStateException("no line with index "
1379:                            + line + " in file " + getAbsolutePath()); // NOI18N
1380:                }
1381:                int outOffset = offset + (column - 1);
1382:                // check that column is valid: not on the next line
1383:                if (text.length() < outOffset
1384:                        || (text.substring(offset, outOffset).indexOf('\n') >= 0)) { // NOI18N
1385:                    throw new IllegalStateException("no column with index "
1386:                            + column + " in file " + getAbsolutePath()); // NOI18N
1387:                }
1388:                return outOffset;
1389:            }
1390:
1391:            /**
1392:             * returns 1-based line and column associated with offset
1393:             * @param offset interested offset in file
1394:             * @return returns pair {line, column}
1395:             */
1396:            public int[] getLineColumn(int offset) {
1397:                int[] lineCol = new int[] { 1, 1 };
1398:                String text = getText();
1399:                if (text.length() < offset) {
1400:                    throw new IllegalArgumentException(
1401:                            "offset is out of file length; "
1402:                                    + // NOI18N
1403:                                    (getBuffer().isFileBased() ? "file based"
1404:                                            : "document based")
1405:                                    + // NOI18N
1406:                                    " file=" + this .getAbsolutePath()
1407:                                    + // NOI18N
1408:                                    ";length=" + text.length() + "; offset="
1409:                                    + offset); // NOI18N
1410:                }
1411:                final int TABSIZE = ModelSupport.getTabSize();
1412:                // find line and column
1413:                for (int curOffset = 0; curOffset < offset; curOffset++) {
1414:                    char curChar = text.charAt(curOffset);
1415:                    if (curChar == '\n') {
1416:                        // just increase line number
1417:                        lineCol[0] = lineCol[0] + 1;
1418:                        lineCol[1] = 1;
1419:                    } else if (curChar == '\t') {
1420:                        int col = lineCol[1];
1421:                        int newCol = (((col - 1) / TABSIZE) + 1) * TABSIZE + 1;
1422:                        lineCol[1] = newCol;
1423:                    } else {
1424:                        lineCol[1]++;
1425:                    }
1426:                }
1427:                return lineCol;
1428:            }
1429:
1430:            public static class SortedKey implements  Comparable<SortedKey>,
1431:                    Persistent, SelfPersistent {
1432:                private int start = 0;
1433:                private CharSequence name;
1434:
1435:                private SortedKey(CsmOffsetableDeclaration declaration) {
1436:                    start = ((CsmOffsetable) declaration).getStartOffset();
1437:                    name = declaration.getName();
1438:                }
1439:
1440:                public int compareTo(SortedKey o) {
1441:                    int res = start - o.start;
1442:                    if (res == 0) {
1443:                        res = CharSequenceKey.Comparator.compare(name, o.name);
1444:                    }
1445:                    return res;
1446:                }
1447:
1448:                public void write(DataOutput output) throws IOException {
1449:                    output.writeInt(start);
1450:                    output.writeUTF(name.toString());
1451:                }
1452:
1453:                public SortedKey(DataInput input) throws IOException {
1454:                    start = input.readInt();
1455:                    name = NameCache.getManager().getString(input.readUTF());
1456:                }
1457:            }
1458:
1459:        }
w__w___w___.___ja_v__a___2__s__.___c___om_ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.