def _compileDependency(self, dep, out, replacements, targetImports, classList): classPattern = re.compile(CoffeescriptBuilder.CLASS_PATTERN) missingPattern = re.compile(CoffeescriptBuilder.MISSING_CLASS_PATTERN) #------------------------------------------------------------------------------------------- # MISSING DEPENDENCIES # Handle missing dependencies if not os.path.exists(dep.path): print("\n\n") self._log.write('ERROR: ' + dep.package + ' package does not exist at: ' + dep.path) return False lastWhitespace = '' openParens = 0 openBrackets = 0 openBraces = 0 skipNextLine = False methodName = '' className = '' registryEntry = None raw = dep.source dep.close() s = '\n\n\t#' + ('%' * 100) + '\n\t#' + ( '%' * 100) + '\n#\t\t' + dep.package + '\n' out.write(s) if dep.allowCaching: cacheOut = open(dep.cachePath, 'w') cacheOut.write(s) else: try: if os.path.exists(dep.cachePath): os.remove(dep.cachePath) except Exception as err: pass cacheOut = None self._log.write('\tCOMPILING: ' + dep.package) analyzer = CoffeescriptAnalyzer(raw, debug=self._debug) analyzer.analyze() #--------------------------------------------------------------------------------------- # COMPILE # Line by line compile to ccs output file for l in analyzer: #----------------------------------------------------------------------------------- # RETARGET CLASS ACCESSORS TO VIZME registry # All classes (except internal class references) are made to # VIZME registry ClassName to prevent class conflicts. for rep in replacements + targetImports: if rep != dep: offset = 0 res = rep.searchPattern.finditer(l.redacted) for r in res: start = r.start() + offset end = r.end() + offset if self._trace: self._log.write('RETARGET: ' + l.source[start:end] + ' | ' + str(r.groupdict())) # Make the replacement and adjust offsets for additional replacements l.insert(start, end, rep.registryName) offset += len(rep.registryName) - end + start #----------------------------------------------------------------------------------- # IDENTIFY CLASS DEFINITIONS # Find class definitions so they can be added to the VIZME registry. res = classPattern.search(l.redacted) if res: registryEntry = self._writeRegistryEntry( out, cacheOut, registryEntry) className = res.group('class').strip() registryEntry = '\n%s.%s ?= %s' % ( CoffeescriptDependency.REGISTRY, className, className) classList.append(className) #----------------------------------------------------------------------------------- # CHECK FOR MISSING CLASSES # Search and find any missing class imports. If a possible missing import is found # flag it in the response. res = missingPattern.finditer(l.redacted) if res: for r in res: cn = r.group('class').strip() start = r.start() if cn == className: continue # Ignore anything in all CAPS! if cn.upper() == cn: continue # Ignore globally defined objects and classes if cn in CoffeescriptBuilder._GLOBAL_CLASSES + analyzer.globalObjects: continue self._warnings.append({ 'id': CoffeescriptBuilder._WARN_ID_MISSING_IMPORT, 'class': cn, 'line': l.lineNumber, 'package': dep.package }) print('\n') self._log.write( 'WARNING: Possible missing import\n\tmissing: %s\n\tfrom: %s [line #%s]' % (cn, dep.package, str(l.lineNumber))) #----------------------------------------------------------------------------------- # LINE DEBUGGER ANALYSIS c = l.redacted.strip() skip = skipNextLine or not l.isSignificant skipNextLine = False if not skip: skips = [ 'class', 'try', 'catch', 'else', 'when', '.', '+', '-', '/', '=', '*', ',', 'and', 'or' ] for s in skips: if c.startswith(s): skip = True break if not skip: skips = ['->', '=>'] methodPattern = re.compile('^(?P<method>[^:]+)') for s in skips: if c.endswith(s): skip = True res = methodPattern.search(c) if res and res.group('method'): methodName = res.group('method') elif c.startswith('$'): methodName = '$' break # Check for line continuations if l.isSignificant: skips = ['.', '+', '-', '/', '=', '*', ',', 'and', 'or'] for s in skips: if c.endswith(s): skipNextLine = True break if self._trace: self._log.write( c.replace('\n', '') + ('\n\t@@@@ skip: ' + str(skip) + '\n\t@@@@ parens: ' + str(openParens) + '\n\t@@@@ braces: ' + str(openBraces) + '\n\t@@@@ brackets: ' + str(openBraces) + '\n\t@@@@ skipNext: ' + str(skipNextLine))) if self._debug and not skip and openParens == 0 and openBraces == 0 and openBrackets == 0: debugLine = 'window.___vmiDebug(\'%s\', \'%s\', \'%s\', %s)\n' % \ (dep.package, className, methodName, str(l.lineNumber)) indent = len(l.indent) > len(lastWhitespace) dedent = len(l.indent) < len(lastWhitespace) skips = [')', ']', '}'] skip = False for s in skips: if c.startswith(s): skip = True break if dedent and skip: lastWhitespace = lastWhitespace else: lastWhitespace = l.indent codePattern = re.compile('(?P<code>[^\s\t\n]+)') res = codePattern.search(c) if not res or len(res.groupdict()['code']) == 0: if self._trace: self._log.write('EMPTY: "' + c + '"') debugLine = '' l.insert(0, 0, l.indent + debugLine) if l.isSignificant: openParens += l.redacted.count('(') - l.redacted.count(')') openBrackets += l.redacted.count('[') - l.redacted.count(']') openBraces += l.redacted.count('{') - l.redacted.count('}') #--------------------------------------------------------------------------------------- # WRITE MODIFIED OUTPUT out.write(l.source) if cacheOut: cacheOut.write(l.source) self._writeRegistryEntry(out, cacheOut, registryEntry) if cacheOut: cacheOut.close() return True